1.1 malloc
void* malloc (size_t size);
1)如果开辟成功,则返回一个指向开辟好空间的指针。
2)如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
3)返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
4)如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
注意: 在用malloc申请内存后一定要检查是否为NULL, 并且这段内存是无类型的内存需要用强制转换强转;
int* arr = (int*)malloc(sizeof(int) * 4);
if(NULL == arr)
return ;
for (int i = 0; i < 4; i++)
{
arr[i] = i;
}
for (int i = 0; i < 4; i++)
{
cout << arr[i] << endl;
}
free(arr);
运行结果
calloc
当有时申请内存需要初始化为0的时候
void* calloc (size_t num, size_t size);
1)函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
2)与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
例如:
char* arr = (char*)calloc(sizeof(int), 5);
if (arr == NULL)
{
return -1;
}
for (int i = 0; i < 5*sizeof(int); i++)
{
cout << arr[i] <<"1" ;
}
free(arr);
calloc将申请来的内存每个字节都设置为0, 将这个字符串打出来对应上面的ASCII可知为‘ ’ ,输出的‘1’ 是为了方便分辨
注意: C语言的提供的函数都需要进行判NULL操作;
ralloc
realloc函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存, 我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。
void* realloc (void* ptr, size_t size);
1)是要调整的内存地址 size 调整之后新大小
2) 返回值为调整之后的内存起始位置。
3)这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
调整的两种情况
情况1 当原来空间有足够的内存,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2 当后面没有足够的内存,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来 使用。这样函数返回的是一个新的内存地址
char* arr = (char*)calloc(sizeof(int), 5);
if (arr == NULL)
{
return -1;
}
char* temp;
temp = (char*)realloc(arr, 4200000000);
if (temp == NULL)
{
cout << "返回NULL" << endl;
}
if (temp == arr)
{
cout << "返回原空间" << endl;
}
for (int i = 0; i < 5*sizeof(int); i++)
{
cout << arr[i] <<"1" ;
}
这里故意用了一个很大的数值, 在申请失败后会返回NULL ,原空间不会释放;
free
void free (void* ptr);
用于释放上面三个函数申请的内存, 如果传入的指针为NULL, 则不干任何事;
由于在堆上申请的内存可以进行跨栈操作所以
void GetMemory(char *p) //(char** p)
{
p = (char *)malloc(100);
}
void Test(void) {
char *str = NULL;
GetMemory(str); //GetMemory(&str) ;
strcpy(str, "hello world");
printf(str);
}
注意: 这个程序是崩溃的, 改为注释后的就可以带出