1、静态内存分配
静态内存分配是在编译时完成的,内存的分配不会在程序运行时改变。变量在程序整个运行周期内都存在,通常是全局变量或局部静态变量。这种方式的内存分配由编译器自动管理,程序员不需要手动控制。
1)全局变量
在函数外部定义,可以在程序的任何部分被访问。
#include <stdio.h>
// 全局变量
int counter = 0;
void increment() {
counter++; // 直接访问全局变量
}
int main() {
printf("初始值:%d\n", counter);
increment();
printf("增加后:%d\n", counter);
return 0;
}
2)局部静态变量
在函数内部定义,使用static
关键字,虽然作用域局限于该函数,但其值在函数调用之间持续存在。
#include <stdio.h>
void function() {
// 静态局部变量
static int num = 0;
num++;
printf("当前值:%d\n", num);
}
int main() {
function(); // 第一次调用:1
function(); // 第二次调用:2
function(); // 第三次调用:3
return 0;
}
2、动态内存分配
动态内存分配是在程序运行时进行的,可以根据需要动态地分配和释放内存。在C语言中,动态内存分配通常通过以下几个标准库函数实现:
1)malloc(size_t size)
分配size
字节的内存块,并返回一个指向它的指针。分配的内存块未初始化。
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 5; // 假设我们想创建一个包含5个整数的数组
int *arr = (int*) malloc(n * sizeof(int)); // 动态分配内存
if (arr == NULL) {
printf("Memory allocation failed\n");
return 1; // 如果内存分配失败,退出程序
}
// 初始化数组
for (int i = 0; i < n; i++) {
arr[i] = i + 1; // 赋值为1, 2, 3, 4, 5
}
// 打印数组元素
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr); // 释放内存
return 0;
}
2)calloc(size_t num, size_t size)
分配足够空间以容纳num
个大小为size
的元素,返回一个指向它的指针,并将所有位设置为0
。
#include <stdio.h>
#include <stdlib.h> // 包含对 calloc 的定义
int main() {
int numElements = 5; // 假设我们需要一个有 5 个元素的数组
// 为 int 类型的数组分配内存
int *arr = (int *)calloc(numElements, sizeof(int));
if (arr == NULL) {
fprintf(stderr, "Memory allocation failed!\n");
return 1; // 如果内存分配失败,返回错误代码
}
// 输出数组的元素,查看它们是否都初始化为 0
printf("The array elements are:\n");
for (int i = 0; i < numElements; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 使用完毕后释放内存
free(arr);
return 0;
}
3)realloc(void *ptr, size_t size)
调整之前由malloc
或calloc
分配的内存块ptr
的大小。如果新大小大于原大小,可能会移动内存块。
#include <stdio.h>
#include <stdlib.h>
int main() {
int* arr = malloc(10 * sizeof(int)); // 初始分配10个整数的空间
if (arr == NULL) {
perror("Initial malloc failed");
exit(1);
}
// 使用arr...
// 重新分配为更大的内存空间
int* temp = realloc(arr, 20 * sizeof(int));
if (temp == NULL) {
perror("Realloc failed");
free(arr); // 重要:失败时,原始内存仍需手动释放
exit(1);
}
arr = temp; // 更新arr指针
// 使用扩展的arr...
free(arr); // 释放内存
return 0;
}
3、区别对比
特性 | 静态内存分配 (int arr[100];) | 动态内存分配 (malloc() 等) |
分配时机 | 编译时 | 运行时 |
内存位置 | 栈(stack)或数据段 | 堆(heap) |
大小是否可变 | ❌ 固定 | ✅ 运行时可变 |
速度 | 快 | 较慢(涉及堆管理) |
释放方式 | 自动释放 | 需要手动 free() |
风险 | 栈溢出(大数组) | 内存泄漏或野指针 |
适合场景 | 小数组、已知大小的变量 | 大数据、需要动态控制大小时 |
4、使用场景
场景 | 推荐方式 |
图像处理,图片大小运行时决定 | 动态内存分配(malloc) |
存储 10 个固定整数 | 静态内存分配 |
长时间存在的链表/树结构 | 动态内存分配 |
临时变量或递归函数局部数组 | 静态内存(栈上) |