函数
malloc
void* malloc(size_t size); 向内存申请一块连续可用的空间,并返回指向这块空间的指针。
如果开辟成功,则返回一个指向开辟好空间的指针;否则返回一个NULL指针,因此malloc的返回值一定要做检查。
calloc
void* calloc(size_t num,size_t size);
calloc与malloc的区别在于:calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
realloc
void* realloc(void* ptr,size_t size); 对动态开辟内存大小的调整。
①要扩展内存就直接在原有内存之后直接追加空间,原来空间的数据不发生变化。
②原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
free
void free(void* ptr); 动态内存的释放和回收
ptr指向的空间不是动态开辟的,那free函数的行为是未定义的;若ptr是NULL指针,则函数什么事都不做。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int num = 0;
scanf("%d", &num);
int *arr= (int*)malloc(num * sizeof(int));
if (arr == NULL)//判断ptr指针是否为空
printf("malloc error\n");
else
printf("malloc success\n");
free(arr);
return 0;
}
注意
- 不能对NULL指针的解引用操作;
- 对动态开辟空间不能越界访问;
- 对非动态开辟内存不能使用free释放;
- 不能使用free释放一块动态开辟内存的一部分;
- 对同一块动态内存不能多次释放;
- 动态开辟内存一定要释放(否则会造成内存泄漏)。
常见错误
char* GetMemory1(void)
{
char p[] = "helloworld";
return p; //返回时内容释放
}
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
int main()
{
char* str1 = NULL;
char* str2 = (char*)malloc(100);
str = GetMemory1(); //开辟后没有内容
printf("%s\n",str1); //输出随机值
GetMemory2(&str1, 100); //指针的址传递
strcpy(str1, "hello");
printf("%s\n",str1); //输出hello
strcpy(str2, "hello");
free(str2);
if (str2 != NULL)
{
strcpy(str2, "world");
printf("%s\n",str2); //证明指针释放了指向的内容,但是指针仍然指向原地址
}
return 0;
}
void GetMemory3(char*p)
{
p = (char*)malloc(100); //栈帧会被释放
}
int main()
{
char* str = NULL;
GetMemory3(str); //指针的值传递无用,str没有开辟内存
strcpy(str, "helloworld"); //程序崩溃
printf("%s\n",str);
return 0;
}
附:
typedef struct st_type
{
int i;
int a[]; //柔性数组成员
} type_a;