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 个固定整数 | 静态内存分配 |
长时间存在的链表/树结构 | 动态内存分配 |
临时变量或递归函数局部数组 | 静态内存(栈上) |