目录

C语言动态内存管理上

C语言动态内存管理(上)

欢迎拜访

本篇主题 :C语言动态内存管理(上)

发布时间 :2025.3.16

隶属专栏

https://i-blog.csdnimg.cn/direct/5875cfcc16044a1f87500b9776ae29e4.gif#pic_center

为什么需要动态内存管理

静态分配的局限性

静态数组: int arr[100] 需要编译时确定,且空间开辟是固定的

自动变量:函数内定义的局部变量生命周期受限于函数栈帧

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。这时候就只能试试动态存开辟了。

动态分配的优势

  • 运行时按需分配(如根据用户输入决定数据规模)
  • 灵活调整内存大小(动态扩容/缩容)
  • 突破栈空间限制(堆空间通常比栈大得多)
  • 实现跨函数的数据持久化(如链表节点)

动态内存函数

malloc

函数介绍

函数地址 :

函数格式 : void* malloc (size_t size);

功能 :分配一个大小字节的内存块,返回一个指向该块开头的指针。新分配的内存块的内容没有初始化,保留不确定的值。

返回值 :如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。

头文件 : strstr 函数的声明在 stdlib.h 的头文件中,在使用时,要使用 #include <stdlib.h> 操作包含头文件。

特别注意 :

  1. 如果size为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。
  2. 该指针的类型始终为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;
}

https://i-blog.csdnimg.cn/direct/57f207bd089c4ce8b7bac4d7eb73942f.png

free

函数介绍

函数地址 :

函数格式 : void free (void* ptr);

功能 :释放了先前通过调用 malloccallocrealloc 分配的内存块,使其再次可用以进行进一步分配。

返回值 : void

头文件 : strstr 函数的声明在 stdlib.h 的头文件中,在使用时,要使用 #include <stdlib.h> 操作包含头文件。

特别注意 :

  1. 如果 ptr 没有指向由上述函数分配的内存块,则会导致未定义的行为。
  2. 如果 ptr 是空指针,则该函数不执行任何操作。
  3. 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;
}

https://i-blog.csdnimg.cn/direct/d300834cc5504ecca48c807d2c219b09.png

calloc

函数介绍

函数地址 :

函数格式 : void* calloc (size_t num, size_t size);

功能 :为包含 num 个元素的数组分配一块内存,每个元素的 size 为字节大小,并将其所有位初始化为零。

返回值 :如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针。

头文件 : strstr 函数的声明在 stdlib.h 的头文件中,在使用时,要使用 #include <stdlib.h> 操作包含头文件。

特别注意 :

  1. 如果 size 为0,则返回值取决于特定的库实现(它可能是也可能不是空指针),但是返回的指针不能被解引用。
  2. 该指针的类型始终为 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;
}

https://i-blog.csdnimg.cn/direct/e0c3023afefb43c79c159945aee722f0.png

realloc

函数介绍(C11标准)

函数地址 :

函数格式 : void* realloc (void* ptr, size_t size);

功能 :改变 ptr 所指向的内存块的大小。

返回值 :如果成功,则返回一个指向函数分配的内存块的指针。如果函数分配请求的内存块失败,则返回空指针,表示 ptr 所指向的块没有被修改。

头文件 : strstr 函数的声明在 stdlib.h 的头文件中,在使用时,要使用 #include <stdlib.h> 操作包含头文件。

特别注意 :

  1. 如果 size 为0,则返回值取决于特定的库实现:它可以是空指针,也可以是其他不能解引用的位置。

  2. 如果 ptr 是空指针,则该函数的行为类似于 malloc ,分配一个新的大小字节块并返回一个指向其起点的指针。

  3. 如果函数分配请求的内存块失败,则返回空指针,并且参数 ptr 指向的内存块不会被释放(它仍然有效,其内容不变)。

  4. 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 的空间。

  5. realloc在调整内存空间的是存在两种情况:

    情况1:原有空间之后有足够大的空间

    情况2:原有空间之后没有足够大的空间

    https://i-blog.csdnimg.cn/direct/9d5e16aee46c4ec3b26f5752e570b4fa.png

    情况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~10
	int 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;
}

https://i-blog.csdnimg.cn/direct/e804822dafbf4a7496d3c6f0446882cd.png

⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!