赞
踩
一:首先我们需要了解malloc的作用是什么,malloc的作用就是动态申请一块内存;
在此之前我们需要引入#include<stdlib.h>头文件
- int main()
- {
- int* arr;
- int i;
- arr=(int*)malloc(sizeof(int)*100); //malloc 申请一块内存
- for(i=0;i<100;i++)
- {
- arr[i]=i;
- }
-
- for(i=0;i<100;i++)
- {
- printf("%d ",arr[i]);
- }
- free(arr);
- arr=NULL
- return 0;
- }
int *ret 其实就是一个指针,指向所申请的空间,所以在malloc函数前我们需要加上()这样的强制转换符
malloc内部我们需要用sizeof计算数据所需要的字节数,比如我想申请100个int型的空间,那么int 所占的字节数就是4或8,我们需要100个那我们就需要乘上100.
因为malloc是在堆上进行使用,使用我们需要手动释放内存;
Malloc:其实就是可以动态申请内存的函数,能很好地弥补静态分配的缺点。
静态分配的缺点:
它申请的内存不能手动释放,它所申请的内存实际上是在栈上申请的,类似如c语言中函数的调用,都是通过在栈上调用内存。栈上调用的函数在执行完成后就会被释放,而在堆上调用的函数则需要手动释放。malloc函数则是在堆上调用的。
那么相比于直接使用arr【100】={0}这种获取内存的方式有什么区别呢?
我们从调用函数来看看:
- #include<stdio.h>
- #include<stdlib.h>
- int* GetArray()
- {
- int ret[100]={0};
- return ret;
-
- }
- int main()
- {
- int i;
- int* arr=GetArray();
- for(i=0;i<100;i++)
- {
- printf("%d ",arr[i]);
- }
- printf("\n");
- return 0;
- }
可以看出打印数组的时候产生了很多的垃圾数据,而且编译器报了警告。
如果我们使用malloc抓住这一段空间,那么会怎么样呢?
- int* GetArray()
- {
- int i;
- //int ret[100]={0};
- int*ret=(int*)malloc(sizeof(int)*100);
- for(i=0;i<100;i++)
- {
- ret[i]=0;
- }
- return ret;
-
- }
- int main()
- {
- int i;
- int* arr=GetArray();
- for(i=0;i<100;i++)
- {
- printf("%d ",arr[i]);
- }
- printf("\n");
- printf("%p",arr);
- free(arr);
- arr=NULL;
结果可以看出数据成功变成了我们所设的数据,这就体现出malloc对于分配内存空间的作用。
关于释放内存
当我们利用指针遍历数组并打印时,我们可以利用malloc获取内存,然后通过指针将其内存首地址存放在一个指针变量中,然后最后我们释放这个指针变量就可以完成内存释放操作。
二:calloc函数:
calloc函数的作用是为我们使用malloc函数申请的那块空间进行初始化,具体操作如下:
- #include<stdio.h>
- #include<stdlib.h>
- int main()
- {
- int* arr;
- int i;
- arr=(int*)malloc(sizeof(int)*100); //malloc 申请一块内存
- /*arr=(int*)calloc(100,sizeof(int)); //calloc 初始化数据
- for(i=0;i<100;i++)
- {
- arr[i]=i;
- }*/
-
- for(i=0;i<100;i++)
- {
- printf("%d ",arr[i]);
- }
- return 0;
- }
当我们不进行初始化操作时,这块空间的值是杂乱的;
当我们进行初始化操作后
- #include<stdio.h>
- #include<stdlib.h>
- int main()
- {
- int* arr;
- int i;
- arr=(int*)malloc(sizeof(int)*100); //malloc 申请一块内存
- arr=(int*)calloc(100,sizeof(int)); //calloc 初始化数据
- for(i=0;i<100;i++)
- {
- arr[i]=i;
- }
-
- for(i=0;i<100;i++)
- {
- printf("%d ",arr[i]);
- }
- return 0;
- }
由此可见,所有值都被初始化为零;
三:realloc 的使用
这里我们可以分为两个情况
第一个情况:小扩容
- #include<stdio.h>
- #include<stdlib.h>
- int* GetArray()
- {
- int i;
- int*ret=(int*)malloc(sizeof(int)*100);
- ret=(int*)calloc(100,sizeof(int)); //calloc 初始化数据
- return ret;
-
- }
- int main()
- {
- int i;
- int* arr=GetArray();
- int* arr1=(int*)realloc(arr,110*sizeof(int));//内存扩容
- for(i=0;i<110;i++)
- {
- arr1[i]=i;
- }
- for(i=0;i<110;i++)
- {
- printf("%d ",arr1[i]);
- }
- printf("\n");
- printf("%p\n",arr);
- printf("%p",arr1);
- free(arr);
- arr=NULL;
- return 0;
- }
通过结果我们可以看出,扩容前的arr和扩容后的arr1的首元素地址都相同,这就是我们的第一种情况
黑色方块代表这块内存已经被使用,如果扩容内存比较小的话,就可以正常进行扩容且首地址是相同的;
如果扩容内存过大那么会造成什么呢?
我们的内存分配情况就会像第三种情况一样,第二种显然是不行的,因为那块空间已经被人利用了,第三种则为在内存充足的地方再划分一块进行分配
这就是大扩容:
代码显示如下:
- #include<stdio.h>
- #include<stdlib.h>
- int* GetArray()
- {
- int i;
- int*ret=(int*)malloc(sizeof(int)*100);
- ret=(int*)calloc(100,sizeof(int)); //calloc 初始化数据
- return ret;
-
- }
- int main()
- {
- int i;
- int* arr=GetArray();
- int* arr1=(int*)realloc(arr,10000*sizeof(int));//内存扩容
- for(i=0;i<10000;i++)
- {
- arr1[i]=i;
- }
- for(i=0;i<10000;i++)
- {
- printf("%d ",arr1[i]);
- }
- printf("\n");
- printf("%p\n",arr);
- printf("%p",arr1);
- free(arr);
- arr=NULL;
- return 0;
- }
可以看出扩容后arr和arr1的首地址不相同了,这也可以验证第三种是正确的;
首地址的不同很可能导致程序会出现错误
扩容的优化:
- #include<stdlib.h>
- #include<stdio.h>
- int* GetArray()
- {
- int i;
- int*ret=(int*)malloc(sizeof(int)*100);
- ret=(int*)calloc(100,sizeof(int)); //calloc 初始化数据
- return ret;
-
- }
- int main()
- {
- int i;
- int* arr=GetArray();
- arr=(int*)realloc(arr,10000*sizeof(int));//内存扩容
- for(i=0;i<10000;i++)
- {
- arr[i]=i;
- }
- for(i=0;i<10000;i++)
- {
- printf("%d ",arr[i]);
- }
- printf("\n");
- printf("%p\n",arr);
- printf("%p",arr);
- free(arr);
- arr=NULL;
我们将arr1改成arr就可以很好的避免首地址不相同的情况了
也可以保证扩容的正确使用;
以上如有错误,感谢指正!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。