C 分配内存
预留内存的过程称为内存分配。内存分配的方式取决于内存的类型。
C 语言有两种类型的内存:静态内存和动态内存。
静态内存
静态内存是指在程序运行之前为变量预留的内存。静态内存的分配也称为编译时内存分配。
C 语言在编译程序时会自动为每个变量分配内存。
例如,如果您创建一个包含 20 个学生的整数数组(例如,用于暑期学期),C 语言将为 20 个元素预留空间,通常为 80 字节的内存 (20 * 4):
但是学期开始后,却发现只有 12 名学生来上课。这样一来,你就浪费了 8 个未使用的元素的空间。
由于你无法更改数组的大小,因此会留下不必要的预留内存。
请注意,程序仍然可以运行,并且不会受到任何损坏。但是,如果你的程序包含大量此类代码,则其运行速度可能会低于最佳运行速度。
如果你想更好地控制已分配的内存,请参阅下面的动态内存部分。
动态内存
动态内存是指在程序开始运行后分配的内存。动态内存的分配也称为运行时内存分配。
与静态内存不同,您可以完全控制任何时候使用的内存量。您可以编写代码来确定所需的内存量并进行分配。
动态内存不属于任何变量,只能通过指针访问。
要分配动态内存,您可以使用 malloc() 或 calloc() 函数。使用这些函数需要包含 头文件。
malloc() 和 calloc() 函数用于分配内存并返回指向该内存地址的指针。
int *ptr1 = malloc(size);
int *ptr2 = calloc(amount, size);
malloc() 函数有一个参数 size,用于指定要分配的内存大小,以字节为单位。
calloc() 函数有两个参数:
- amount - 指定要分配的内存项的数量
- size - 指定每个内存项的大小,以字节为单位。
注意: 使用 malloc() 分配的内存中的数据是不可预测的。为避免出现意外值,请确保在读取内存之前先写入一些数据。
与 malloc() 不同,calloc() 函数会将分配的所有内存都写入零。然而,这使得 calloc() 的效率略低。
为数据类型分配合适内存量的最佳方法是使用 sizeof 运算符:
int *ptr1, *ptr2;
ptr1 = malloc(sizeof(*ptr1));
ptr2 = calloc(1, sizeof(*ptr2));
注意: sizeof(ptr1) 告诉 C 语言测量指定地址处数据的大小。如果您忘记使用 * 而写成 sizeof(*ptr1),它将测量指针本身的大小,也就是存储内存地址所需的(通常)8 个字节。
注意: sizeof 运算符无法测量动态内存的分配量。测量动态内存时,它只能告诉您内存中数据类型的大小。例如,如果您为 5 个 float 值预留空间,则 sizeof 运算符将返回 4,即单个 float 值所需的字节数。
让我们利用动态记忆来改进上面学生的例子。
如前所述,我们不能使用 sizeof 来衡量分配了多少内存,我们必须通过将项目数量乘以数据类型的大小来计算:
示例
int *students;
int numStudents = 12;
students = calloc(numStudents, sizeof(*students));
printf("%d", numStudents * sizeof(*students)); // 48 bytes
亲自试一试 »
备注
使用动态内存分配时,您还应该在程序结束时检查错误并释放内存。您将在后续章节中了解更多相关内容。
栈内存
为了完整起见,值得一提的是栈内存。栈内存是一种动态内存,专门用于存放在函数内部声明的变量。函数内部声明的变量使用栈内存,而不是静态内存。
当函数被调用时,会为函数内部的变量分配栈内存。函数返回时,栈内存会被释放。
了解栈内存有助于处理嵌套函数调用和递归的内存使用情况。递归重复次数过多可能会占用过多的栈内存。这种情况称为栈溢出。

