【C语言菜鸟知识】——动态内存管理
-------------------------------------------------------------------------------------------------------------------------------------
< 1、栈 >
在全局变量是分配在内存中的静态储存区,非静态的局部变量是分配在内存中的动态储存区,这个储存区就是栈的区域。
< 2、堆 >
在内存中允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必声明部分定义,也不必等到函数结束时才释放,需要时可以随时开辟,不需要时随时释放。这些数据临时存放在一个特别的自由储存区,就是堆区。只能通过指针来引用。
现在我们已学了两种开辟空间的方式,其一:int a = 0;这种一次开辟一小块空间,其二:int arr[10] = { 0 };这种一次开辟一大块空间。但这两种开辟方式是有局限性的,一旦开辟就无法再更改开辟空间的大小了。
举个例子:现创建了一个结构体数组,数组每个元素都是一个人的信息,而该数组能存放100个人的信息。但我仅需要存放3个人的信息,对于这个结构体数组来说,剩余的97个空间不就浪费了嘛;同理我需要存放120个人的信息,对于该数组来说是放不下的,而我又不能对其大小进行修改。
这两种开辟空间的方式是在栈区上开辟;栈区中申请的空间是固定死的无法修改。而动态内存是在堆区开辟空间。
对于内存的动态分配管理,包括动态内存函数:malloc、calloc、realloc、free。要使用这几个函数就必须先引用一个头文件<stdlib.h>才行。
< 3、malloc >
在C语言中提供了动态内存分配的函数:
void* malloc(size_t size)
通过malloc函数,可以在堆区申请一块连续可用的空间供我们使用。
size ——表示我们要开辟多大的一块内存空间(单位是字节)。
该函数返回一个指针,指向已分配大小的内存。如果请求失败,则返回 NULL。
注意:
malloc内的参数是需要动态分配的字节数,而不是可以存储的元素个数!
当动态分配内存时,存储的是字符型数据,每个元素1字节,所以字节数刚好等于需要存储的元素个数(字符数+1);
如果存储的是整型或浮点型数据,字节数等于“需要存储的元素个数 * 一个元素的字节数”,
代码格式为:
type *var_name = (type*)malloc(sizeof(type)*num);
< 4、free >
free函数是专门用来释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。
void free(void* ptr)
1.ptr是我们申请的内存空间的起始地址。
2.如果ptr不是指向我们所开辟得内存空间,这是free函数未定义的,编译不会通过。
3.如果ptr是个空指针,那么free函数什么也不会做。
< 5、calloc >
calloc和malloc作用都是开辟一块内存空间。
void* calloc(size_t num,size_t size);
1、nitems -- 要被分配的元素个数。
2、size -- 元素的大小。
3、calloc会在内存中开辟num个大小为size的元素空间,并把空间的每个字节初始化为0。
4、malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。
注意:
calloc() 函数将分配的内存全部初始化为零。如果不需要初始化,可以使用 malloc() 函数代替。另外,使用 calloc() 函数时需要注意,如果分配的内存块过大,可能会导致内存不足的问题。
< 6、realloc >
realloc作用就是扩容
void* realloc(void* ptr,size_t size)
该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。
Ptr——指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
Size——内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。
1.ptr是要调整的内存空间的地址
2.size是调整后的空间大小
3.realloc调整可能面对下面两种情况:
a.内存空间后面还有足够大的空间,那么内存地址不变,内存空间变大。
b.内存空间后面没有足够大的空间,那么会找一个新的足够大的内存地址,将原内存空间的内容复制拷贝到新的内存地址空间,内存地址改变。
< 7、实例 >
//使用 malloc分配了五个元素大小的动态分配内存,并将返回的指针赋给 data
data = (uint8_t*) malloc(5 * sizeof(uint8_t));
if (data == NULL)
{
// 内存分配失败,采取适当的处理措施
printf("内存分配失败\n");
return;
}
// 将数据复制到 data 中
data[0] = 1;
data[1] = 2;
data[2] = 3;
data[3] = 4;
data[4] = 5;
/* 打印最初的内存分配 */
printf("Data1 = ");
for (u8 i = 0; i < 5; i++)
{
printf("%d ", data[i]);
}
printf("\n");
// 使用 realloc函数重新分配内存,将原先的五个元素扩展为十个元素大小的内存块
data = (uint8_t*)realloc(data, 10 * sizeof(uint8_t));
if (data == NULL)
{
// 内存重新分配失败,采取适当的处理措施
printf("内存重新分配失败\n");
return;
}
// 将新的数据复制到 data 中
data[5] = 6;
data[6] = 7;
data[7] = 8;
data[8] = 9;
data[9] = 0;
/* 打印重新的分配内存 */
printf("Data2 = ");
for (u8 i = 0; i < 10; i++)
{
printf("%d ", data[i]);
}
printf("\n");
//使用 free函数释放了 data 数组的内存
free(data);
打印出来结果:
使用 malloc分配了五个元素大小的动态分配内存,打印出来这五个元素。1、2、3、4、5
使用 realloc函数重新分配内存,将原先的五个元素扩展为十个元素大小的内存块。1、2、3、4、5、6、7、8、9、0

浙公网安备 33010602011771号