c语言动态内存分配
静态内存分配: 在进程的地址空间中,代码区、常量区、全局数据区的内存在程序启动时就已经分配好了,它们大小固定,不能由程序员分配和释放,只能等到程序运行结束由操作系统回收。
动态内存分配: 栈区和堆区的内存在程序运行期间可以根据实际需求来分配和释放,不用在程序刚启动时就备足所有内存。
动态内存的优点:可以让程序对内存的管理更加灵活和高效,需要内存就立即分配,而且需要多少就分配多少,从几个字节到几个GB不等;不需要时就立即回收,再分配给其他程序使用。
动态内存分配函数
在堆上分配和释放内存需要用到C语言标准库中的几个函数:malloc()、calloc()、realloc() 和 free()。
- malloc()
原型:void* malloc (size_t size);
作用:在堆区分配 size 字节的内存空间。
返回值:成功返回分配的内存地址,失败则返回NULL。
注意:
- 函数的返回值类型是 void ,void 并不是说没有返回值或者返回空指针,而是返回的指针类型未知。所以在使用 malloc() 时通常需要进行强制类型转换,将 void 指针转换成我们希望的类型。
- 分配内存在动态存储区(堆区),手动分配,手动释放。
- 申请时空间可能有也可能没有,需要自行判断。
- calloc()
原型:void* calloc(size_t n, size_t size);
功能:在堆区分配 n*size 字节的连续空间。
返回值:成功返回分配的内存地址,失败则返回NULL。
注意:
- calloc() 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。
- calloc() 与 malloc() 的一个重要区别是:calloc() 在动态分配完内存后,自动初始化该内存空间为零,而 malloc() 不初始化,里边数据是未知的垃圾数据。
- realloc()
原型:void* realloc(void *ptr, size_t size);
功能:对 ptr 指向的内存重新分配 size 大小的空间。
返回值:成功返回更改后的内存地址,失败则返回NULL。
- free()
原型:void free(void* ptr);
功能:释放由 malloc()、calloc()、realloc() 申请的内存空间。
几点注意
-
每个内存分配函数必须有相应的 free 函数,释放后不能再次使用被释放的内存。
-
free ( ) 并不能改变指针的值,指针依然指向以前的内存,为了防止再次使用该内存,建议将指针的值手动置为 NULL。
-
sizeof 是一个单目操作符,不是函数,用以获取数据类型的长度时必须加括号,例如 sizeof(int)、sizeof(char) 等。
最后是一个综合的示例:
#include <stdio.h>
#include <stdlib.h>
#define N (5)
#define N1 (7)
#define N2 (3)
int main()
{
int *ip;
int *large_ip;
int *small_ip;
if((ip = (int*)malloc(N * sizeof(int))) == NULL)
{
printf("memory allocated failed!\n");
exit(1);
}
int i;
for(i = 0; i < N; i++)
{
ip[i] = i;
printf("ip[%d] = %d\t", i, ip[i]);
}
printf("\n");
if((large_ip = (int* )realloc(ip, N1 * sizeof(int))) == NULL)
{
printf("memory allocated failed!\n");
exit(1);
}
for(i = N; i < N1; i++)
large_ip[i] = 9;
for(i = 0; i < N1; i++)
printf("large_ip[%d] = %d\t", i, large_ip[i]);
printf("\n");
if((small_ip = (int*)realloc(large_ip, N2 * sizeof(int))) == NULL)
{
printf("memory allocated failed!\n");
exit(1);
}
for(i = 0; i < N2; i++)
printf("small_ip[%d] = %d\t", i, small_ip[i]);
printf("\n");
free(small_ip);
small_ip = NULL;
system("pause");
return 0;
}