欢迎拜访:雾里看山-CSDN博客
本篇主题:C语言动态内存管理(上)
发布时间:2025.3.16
隶属专栏:C语言
目录
- 为什么需要动态内存管理
- 静态分配的局限性
- 动态分配的优势
- 动态内存函数
- malloc
- 函数介绍
- 函数使用
- free
- 函数介绍
- 函数使用
- calloc
- 函数介绍
- 函数使用
- realloc
- 函数介绍(C11标准)
- 函数使用
为什么需要动态内存管理
静态分配的局限性
静态数组:int arr[100]
需要编译时确定,且空间开辟是固定的
自动变量:函数内定义的局部变量生命周期受限于函数栈帧
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。这时候就只能试试动态存开辟了。
动态分配的优势
- 运行时按需分配(如根据用户输入决定数据规模)
- 灵活调整内存大小(动态扩容/缩容)
- 突破栈空间限制(堆空间通常比栈大得多)
- 实现跨函数的数据持久化(如链表节点)
动态内存函数
malloc
函数介绍
函数地址:malloc
函数格式:void* malloc (size_t size);
功能:分配一个大小字节的内存块,返回一个指向该块开头的指针。新分配的内存块的内容没有初始化,保留不确定的值。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。
头文件: strstr
函数的声明在stdlib.h
的头文件中,在使用时,要使用#include <stdlib.h>
操作包含头文件。
特别注意:
- 如果size为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。
- 该指针的类型始终为void*,可以将其强制转换为所需的数据指针类型,以实现可解引用。
函数使用
#include <stdio.h>
#include <stdlib.h> int main()
{int i, n;char* buffer;printf("How long do you want the string? ");scanf("%d", &i);buffer = (char*)malloc(i + 1);if (buffer == NULL) exit(1);for (n = 0; n < i; n++)buffer[n] = rand() % 26 + 'a';buffer[i] = '\0';printf("Random string: %s\n", buffer);free(buffer);return 0;
}
free
函数介绍
函数地址:free
函数格式:void free (void* ptr);
功能:释放了先前通过调用malloc
、calloc
或realloc
分配的内存块,使其再次可用以进行进一步分配。
返回值:void
头文件: strstr
函数的声明在stdlib.h
的头文件中,在使用时,要使用#include <stdlib.h>
操作包含头文件。
特别注意:
- 如果
ptr
没有指向由上述函数分配的内存块,则会导致未定义的行为。 - 如果
ptr
是空指针,则该函数不执行任何操作。 free
函数没有改变ptr
本身的值,因此它仍然指向相同的(现在无效的)位置。
函数使用
#include <stdlib.h> int main()
{int* buffer1, * buffer2, * buffer3;buffer1 = (int*)malloc(100 * sizeof(int));buffer2 = (int*)calloc(100, sizeof(int));buffer3 = (int*)realloc(buffer2, 500 * sizeof(int));free(buffer1);free(buffer3);return 0;
}
calloc
函数介绍
函数地址:calloc
函数格式:void* calloc (size_t num, size_t size);
功能:为包含num
个元素的数组分配一块内存,每个元素的size
为字节大小,并将其所有位初始化为零。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。
头文件: strstr
函数的声明在stdlib.h
的头文件中,在使用时,要使用#include <stdlib.h>
操作包含头文件。
特别注意:
- 如果
size
为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。 - 该指针的类型始终为
void*
,可以将其强制转换为所需的数据指针类型,以实现可解引用。
函数使用
#include <stdio.h>
#include <stdlib.h> int main()
{int* p = (int*)calloc(10, sizeof(int));if (p != NULL){//使用空间}free(p);p = NULL;return 0;
}
realloc
函数介绍(C11标准)
函数地址:realloc
函数格式:void* realloc (void* ptr, size_t size);
功能:改变ptr
所指向的内存块的大小。
返回值:如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针,表示ptr
所指向的块没有被修改。
头文件: strstr
函数的声明在stdlib.h
的头文件中,在使用时,要使用#include <stdlib.h>
操作包含头文件。
特别注意:
- 如果
size
为0,则返回值取决于特定的库实现:它可以是空指针,也可以是其他不能解引用的位置。 - 如果
ptr
是空指针,则该函数的行为类似于malloc
,分配一个新的大小字节块并返回一个指向其起点的指针。 - 如果函数分配请求的内存块失败,则返回空指针,并且参数
ptr
指向的内存块不会被释放(它仍然有效,其内容不变)。 - 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到
新
的空间。 - realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有足够大的空间
情况2:原有空间之后没有足够大的空间
情况1:当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:当是情况2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
由于上述的两种情况,realloc
函数的使用就要注意一些。
函数使用
#include <stdio.h>
#include <stdlib.h> int main()
{int* p = (int*)malloc(40);if (p == NULL){perror("malloc");return 1;}//初始化为1~10int i = 0;for (i = 0; i < 10; i++) {p[i] = i + 1;}//增加一些空间int* ptr = (int*)realloc(p, 8000);if (ptr != NULL){p = ptr;ptr = NULL;}else{perror("realloc");return 1;}//打印数据for (i = 0; i < 20; i++){printf("%d\n", p[i]);}//释放free(p);p = NULL;return 0;
}
⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!