动态内存分配

动态内存分配

背景

以前如果需要从键盘输入数组的范围并定义是行不通的。

只能定义一个较大的值作为数组的大小,此时数组长度必须在编译的时候确定

动态数组允许你在程序运行过程中(Runtime)才决定数组的大小。

有:

1
2
3
4
5
6
7
8
9
10
11
12
13
语言: C)产生动态数组,编写程序,输入数组大小后,通过动态分配内存函数malloc产生数组。
**输入格式要求:"%d" 提示信息:"Enter array size:"
**输出格式要求:"array[%d]=%d\n"
程序运行示例如下:
Enter array size:8
array[0]=0
array[1]=10
array[2]=20
array[3]=30
array[4]=40
array[5]=50
array[6]=60
array[7]=70

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <stdlib.h> // 必须包含这个头文件才能使用 malloc 和 free

int main() {
int size;
int *array; // 定义一个指针,用于指向动态分配的内存地址
int i;

// 1. 提示并输入数组大小
printf("Enter array size:");
scanf("%d", &size);

// 2. 动态分配内存
// malloc 返回的是 void*,通常建议显式转换为 int*
// 分配的大小是:元素个数 * 每个元素占用的字节数
array = (int*)malloc(size * sizeof(int));

// 检查内存是否分配成功(虽然小程序通常不会失败,但在工程中这是必须的)
if (array == NULL) {
printf("Memory allocation failed!\n");
return 1;
}

// 3. 赋值并按照格式输出
// 根据你的示例,规律是:数值 = 下标 * 10
for (i = 0; i < size; i++) {
array[i] = i * 10;
printf("array[%d]=%d\n", i, array[i]);
}

// 4. 释放内存
// 动态分配的内存必须手动释放,否则会导致内存泄漏
free(array);

return 0;
}

(int*)malloc(size * sizeof(int))这一句话中的占用的字节数可不可以输入数字来替代?

可以,但不推荐。

sizeof(int) 的作用是获取 int 类型在当前计算机上占用的字节数。

  • 在现代常见的电脑上,int 通常是 4 字节。
  • 所以写 malloc(size * 4)malloc(size * sizeof(int)) 效果是一样的。

为什么不推荐写死数字? 因为可移植性(Portability)

  • 有些老式嵌入式系统或特殊的单片机,int 可能是 2 字节。
  • 如果你写死了 4,放到那台机器上,你的数组就会变得比预期大,或者出现内存对齐错误。
  • 使用 sizeof(int),编译器会自动帮你判断当前机器是几字节,代码更健壮。

可不可以换成char,即给char类型的数组分配内存的时候?

完全可以

NULL这个到底是啥?

在 C 语言的定义里,它长这样:

1
#define NULL ((void *)0)

你可以把它理解为一个“无效地址”或者“空地址”

  • 在内存里,地址 0 是受操作系统严格保护的,任何程序都不允许读写这个地址。
  • 所以,当我们把一个指针指向 NULL,就是明确表示:这个指针目前不指向任何有效的东西

NULL 的值: 在 C 语言中,NULL 是一个宏,用于表示空指针。在大多数编译器和标准库实现中,它通常被定义为整数 0 或者 ((void *)0)。无论哪种定义,其底层的数值表示都是 0

打印结果: 当 printf("%d\n", NULL); 执行时,它会将 NULL 对应的值(即 0)按照整数格式打印出来。因此,输出结果将会是 0

array == NULL是怎么实现检查内存是否分配成功的?

malloc 的内部逻辑大致如下(简化版):

  1. 你去告诉操作系统:“我要 100 字节内存”。
  2. 操作系统去堆(Heap)里找,看有没有连续的 100 字节空地。
  3. 情况一(成功): 找到了。操作系统把这块地的首地址(比如 0x12345678)返回给你。
    • 这时 array 等于 0x12345678,不等于 NULL
  4. 情况二(失败): 内存满了,或者你要的太大了(比如你要 1000GB),实在找不到了。操作系统就会返回 **NULL**。
    • 这时 array 等于 NULL

所以,if (array == NULL) 这行代码就是在问:“操作系统,你刚才给我分配内存的时候,是拒绝我了吗?”

free(array);中为什么动态分配的内存必须要释放?

​ 打个比方:酒店 vs. 家

  • 栈内存(Stack - 也就是普通的变量): 像是你的
    • 你回家(函数开始),住进去,出门(函数结束),灯自动关,房间自动空出来。系统自动管理,不需要你操心。
  • 堆内存(Heap - 也就是 malloc 的内存): 像是住酒店
    • malloc 就是你去前台办理入住(申请房卡)
    • 你在房间里睡觉、放东西(存数组数据),这叫“使用”。
    • 关键点来了: 当你离开酒店(程序跑去执行别的函数了),如果你不去前台退房(free),酒店系统会认为你还住在里面
什么是内存泄漏(Memory Leak)?

你走了,但没退房。

  1. 对于你(程序)来说: 你的指针变量 array 可能在函数结束时销毁了(你把房卡丢了)。你再也找不到那个房间了,你也无法再使用它。
  2. 对于酒店(操作系统)来说: 电脑显示那个房间“占用中”。如果有新客人来,酒店不能把这个房间给别人。

后果: 如果你写了一个死循环或者服务器程序(长期运行),不断地 malloc 却不 free(不断开房不退房),酒店的房间很快就会全部爆满。 最终,物理内存被耗尽,操作系统会强制杀掉你的程序,甚至导致电脑死机。这就是内存泄漏


动态内存分配
http://example.com/2025/12/17/动态内存分配/
作者
王柏森
发布于
2025年12月17日
许可协议