首页 > 其他分享 >再次学习malloc()

再次学习malloc()

时间:2023-04-19 19:22:55浏览次数:46  
标签:char malloc 再次 函数 int 学习 数组 指针

在力扣做题,发现给的函数是char ** fizzBuzz(int n, int* returnSize)这种类型的,也就是返回的是一个二级指针

题目
给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:

answer[i] == "FizzBuzz" 如果 i 同时是 3 和 5 的倍数。
answer[i] == "Fizz" 如果 i 是 3 的倍数。
answer[i] == "Buzz" 如果 i 是 5 的倍数。
answer[i] == i (以字符串形式)如果上述条件全不满足。
示例 1:
输入:n = 3
输出:["1","2","Fizz"]
示例 2:
输入:n = 5
输出:["1","2","Fizz","4","Buzz"]
代码
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char ** fizzBuzz(int n, int* returnSize)
{
    char **ans;
		ans=(char **) malloc (sizeof(char*)*n);

	for(int i=1;i<=n;i++)
	{
		if(i%3==0&&i%5==0)
		{
			ans[i-1]="FizzBuzz";  // ans才是二级指针,ans[i-1]中储存的是指针,字符串可以直接赋值给指针;
		}
		else if(i%3==0)
		{
			ans[i-1]="Fizz";      // 字符串常量不需要分配内存,指针储存了它的地址;
		}
		else if(i%5==0)
		{
			ans[i-1]="Buzz";
		}
		else
		{
			ans[i-1]=(char**)malloc(sizeof(char*));  // 不是字符串常量,需要分配地址和内存,需要malloc();
			sprintf(ans[i-1],"%d",i);
		}
	}
    *returnSize=n;
    return ans;
}

以前用过的是int* twoSum(int* nums, int numsSize, int* returnSize)这样的,这里int* twoSum()代表函数返回一个指针(其实就是一个数组),nums是在函数外声明的数组,numsSize是数组nums的元素个数,returnSize是返回地址处储存元素的个数的地址。

为什么这么说?什么叫“地址处储存元素的个数”?

因为数组名和数组的首元素地址等价,如果return ans;就等价于return &ans[0],所以函数如果返回一个指针,那这个指针有可能是指向一个单个值,也有可能指向一个数组。这里的returnSize是一个指针,我们通过*returnSize=size把这些信息传递出去。
所以可以看到,这个函数做到了“传入数组”和“返回数组”。

既然数组也可以视为指针,为什么要用malloc()创建数组?

这涉及到变量的储存方式,简单来说:
  • 如果直接用数组,那么这个数组的生命只有这个函数的大括号这么长,因为它是属于这个函数的局部变量。
  • 如果使用malloc(),那么这个数组的生命将持续到内存被free()释放或者main()结束。
局部变量储存在“栈”中,这是由系统自行分配的,程序员无法插手,所以使用受到限制,但优点是速度快。用malloc()分配的变量储存在“堆”中,这个内存是由程序员控制的,在没有使用free()释放的情况下,将持续到程序结束。

所以我在初次学习malloc()中遇到的那句Note: The returned array must be malloced, assume caller calls free().,其意思就是,不要使用局部变量,要使用malloc(),这样力扣才能得到你储存的东西(这句话出现次数多是因为力扣总是给一个函数,而不是让自己写程序,所以只能考虑到函数的一些局限性)。

可是有一个问题,我在上个博客中说过,如果malloc()free()不成对使用,那么就有内存泄漏的风险。那我在函数中是否也要成对写呢?如果成对写,内存还是在函数中就被释放,和局部变量无异。如果不成对写,又有内存泄漏的风险,怎么办?

不用担心,他告诉了assume caller calls free(),也就是让你假设函数的调用者调用了free(),所以你才必须使用malloc(),因此不用在函数中使用free(),不用担心内存泄漏的问题。
另:如果在函数内使用了free(),会怎么样?有时还是会正常输出,但是这里储存的东西变成了未定义的。

回过头来,我们看一开始的返回值为二级指针的函数。

首先我们肯定还是要使用malloc(),但是返回值为二级指针,写法如下:
char **ans = (char**) malloc(sizeof(char*)*size);
指针是储存某个值地址的变量,那么二级指针就是储存这些指针的地址的变量。
前面说过,指针可以看作是数组,只不过元素个数没有声明而已。那么二级指针,就可以看作是二维数组。
举个例子就能明白:
// 3个字符数组
char a[3]={'1','2','3'};
char b[2]={'4','5'};
char c[1]={'6'};
// 3个指向储存字符类型值的指针
char *a1,*b1,*c1;
// 储存数组的地址
a1=&a;
b1=&b;
c1=&c;
// 1个指向储存字符类型值的指针的指针
char **a2[3]={&a1,&b1,&c1};
// 这个二级指针a2的效果如下:
a2 -> a1 -> a = {'1','2','3'}
   -> b2 -> b = {'4','5'}
   -> c2 -> c = {'6'}

在这个题目中,返回的是元素为字符串的数组,而我们知道字符串就是特殊的字符数组,因此返回值本身就应该是二维数组。而这里没有用二维数组,而是二维指针的原因,前面已经说了,局部变量只能在函数内使用,所以必须要使用malloc()

标签:char,malloc,再次,函数,int,学习,数组,指针
From: https://www.cnblogs.com/Hubugui/p/17332852.html

相关文章

  • 星起航运营公司靠谱吗?美国电商销售增长率将再次超过20.7%!
    星起航运营公司是靠谱的。武汉星起航公司涉足亚马逊行业已经有7年时间,在整个新手孵化行业是非常知名的一家公司,这源于他们自身非常丰富的经验,同时把这些经验都复制给想要从事亚马逊行业的新商家。我们都知道,亚马逊的主要市场聚集在北美跟欧洲发达国家,而北美三个国家中,美国的人均收......
  • PyTorch实现联邦学习堆叠自编码器
    联邦学习是一种用于训练分布在不同设备或地点的模型的技术,其中数据分布在不同的设备上,且不会离开设备。每个设备只训练其本地数据的模型,并将更新的模型参数传递给服务器,服务器对这些更新进行聚合以更新全局模型。由于不共享原始数据,因此联邦学习能够提供更好的数据隐私和安全性......
  • 数据结构与算法学习01
    学习要点一、预习页码:2-27二、预习内容1、数据结构基本定义:数据、数据元素、数据项、数据对象,重点理解数据结构的定义。2、理解逻辑结构。集合、线性结构、树形结构、图形结构。数学描述方法。3、理解存储结构。顺序存储结构、链式存储结构、索引存储结构和哈希存储结构。4......
  • 数据结构与算法学习02
    学习要点一、复习内容重点及难点:算法的时间复杂度分析。过程:(1)找寻循环中的最内层语句(2)分析该语句的执行次数。二、预习内容1、预习页码:21-22,30,32-422、具体预习内容(1)算法的平均时间复杂度分析。不能用最好和最坏的极端情况分析算法,应该用等概率的平均时间复杂度来进行分析......
  • 数据结构与算法学习04
    学习要点1、预习页码:47-542、预习内容:(1)单链表建立的头插法和尾插法。(重点)两种方法的不同级效果。(2)线性表的基本运算在单链表中的实现。(9个算法)重点掌握在9个算法中,如何计算单链表的长度(采用循环计数的方式),单链表越界的描述,单链表中节点的查找,单链表节点的插入和删除操作。(重点......
  • 数据结构与算法学习03
    学习要点一、预习页码:38-51二、预习内容1、顺序表应用实例——P38---例题2.3+例题2.4,练习题P71---6。2、线性表的实现——单链表(必须掌握),构造过程,见P43-图2.113、单链表的定义,见P44--最后四行4、熟练掌握单链表的插入删除操作。(重点掌握)——图2.14+图2.155、(重点掌握)单链表......
  • 数据结构与算法学习06
    学习要点一、预习页码:57-60、79-83二、预习内容1、理解双链表和单链表的区别,能熟练运用单链表算法改进并适用双链表。例如双链表插入和删除操作,双链表逆置操作(教材P57--例题2.9),双链表排序操作(教材P57--例题2.10),和教材P53--例2.8比较。2、循环链表(包含循环单链表和循环双链表)的......
  • 数据结构与算法学习05
    学习要点一、复习内容:单链表头插法和尾插法及核心代码,能运用头插法和尾插法完成基于单链表建表的算法应用问题。二、预习页码:52-60三、预习内容1、基于单链表查询的算法的设计过程。阅读代码P52--例2.7+2.8,能熟练掌握单链表的查找算法。2、双链表的基本构造(包括基本概念+画图......
  • docker学习
    镜像(image)镜像可以理解为一个模板,里边有一些东西,可以通过run命令来进行运行。通过某一个镜像可以创建多个容器(最终的服务或者是项目就是运行在容器里边的) 容器(container)Docker利用容器技术可以独立运行一个或者一组应用。可以通过镜像运行启动、停止、删除的基本命令目前可......
  • springboot学习之五(自动配置)
    一、@Conditional源码springboot的自动配置是通过@Conditional注解(条件判断)实现的.@Conditional是Spring4版本新提供的一种注解,它的作用是按照设定的条件进行判断,把满足判断条件的bean注册到Spring容器。packageorg.springframework.context.annotation;importjava.lang.a......