动态内存开辟是根据用户的需要来开辟开间,是在堆上开辟空间的。
1.malloc:
用于开辟一块连续的内存空间。
- 函数原型:void *malloc( size_t size );
- malloc函数的返回值是一个void类型的指针,参数为无符号类型数据即申请分配的内存大小,单位是字节。
- 内存开辟成功,返回这块空间的首地址,失败返回空指针,所以需要判空处理,
if(p != NULL)。成功的话就需要指针来接受这个地址。但是由于函数的返回值是void * 的,所以需要强制转换成你所接收的类型。接收存什么类型的数据就转换成什么类型的指针。如下:
char *p=(char *)malloc(100);
在堆上分配100个字节的空间,返回这块空间首地址,把地址强转成char 类型后赋给char 类型的指针变量p,同时说明这块空间存放char类型的数据。
这里有一个问题????用malloc函数申请0字节内存会返回空指针吗?
答:测试一下,申请0字节,函数并不返回空指针,而是返回一个正常的地址。但是这块大小为0的内存无法使用。这时候判空语句 if(p != NULL)将不起作用。。。
char*p = (char*)malloc(0);
printf("%p\n", p);
2.内存释放:free
有开辟空间,就一定有分配。不然内存迟早会用完。来看一下free函数。
- 函数原型:void free( void *memblock );
- free函数只有一个参数,就是所要释放内存块的首地址。free(p);
- free函数就是把申请的这块内存和p之间的关系斩断,从此p和那块空间没有关联。但是p本身保存的地址并没有改变,但是它对这个地址处的那块内存已经没有使用权了。那块被释放的内存里的保存的值也没有改变,只是不能使用。所以在释放之后要进行置空处理,否则这块指针就成了一个野指针。
看一下这道题:
void Test(void)
{
char *str = (char *)malloc(100);
strcpy(str, “hello”);
free(str);
if (str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
在free(p)之后,p所指向的内存被释放,但是p所指的地址仍然不变。然后进行判空处理,这是一种无效的判空。所以free完之后一定要把指针置空。
3.calloc:
用于开辟一块连续的空间,并且把这块空间初始化为0.
- 函数原型:void* calloc (size_t num, size_t size);
- 功能:为 num 个大小为 size 的元素开辟⼀一块空间,所以开辟的总字节数为num*size个字节,并且把空间的每个字节初始化为 0。
- 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为 全0。下栗是连续开辟5个int型字节的空间即20个字节空间。
char*p = (char*)calloc(5, sizeof(int));
realloc:
调整内存大小。
1. 函数原型:void *realloc( void *memblock, size_t size );
2. 功能:memblock是调整的内存块的地址,size是调整后的内存大小。
3. 返回值为调整之后的内存起始位置。
4. realloc调整内存空间有两种情况:
原有空间之后有足够的空间,要扩展内存之间在这块地址后追加内存就可以了。
原有空间之后没有足够的空间,扩展的方法是:在堆上重新找一块合适大小的空间来使用,这样函数返回的是一个新的内存地址空间。
int *ptr = malloc(100);
if (ptr != NULL)
{
// 业务处理
}
else
{
exit(EXIT_FAILURE);
}
int *p = NULL;
p = realloc(ptr, 2000);
if (p != NULL)
{
ptr = p;
}
// 业务处理
free(ptr);
ptr = NULL;
先开辟一块内存空间,发现不够用,后再用realloc调整内存大小。用realloc在开辟时如果后边的空间不够用的话,会重新找一块空间,这时返回的就是新的空间的地址。