1. 栈空间(Stack)
-
用途:用于存储函数调用时的局部变量、函数参数、返回地址等。
-
特点:
-
由编译器自动管理。
-
内存分配和释放速度快(只需移动栈指针)。
-
空间有限,通常较小(几MB)。
-
后进先出(LIFO)结构。
-
-
生命周期:函数调用时分配,函数返回时自动释放。
-
示例:
void func() { int x = 10; // x分配在栈上 } // 函数结束,x的栈空间自动释放
2. 堆空间(Heap)
-
用途:用于动态内存分配(如
malloc
、calloc
、realloc
等)。 -
特点:
-
需要手动管理内存的分配和释放(使用
malloc
和free
)。 -
空间较大,受系统内存限制。
-
分配和释放速度较慢。
-
-
生命周期:由程序员控制,分配后需手动释放,否则会导致内存泄漏。
-
示例:
-
int *ptr = (int *)malloc(sizeof(int) * 10); // 在堆上分配内存 free(ptr); // 手动释放堆内存
3. 全局/静态存储区(Global/Static Storage)
-
用途:用于存储全局变量和静态变量。
-
特点:
-
分为两个区域:
-
已初始化数据区:存储已初始化的全局变量和静态变量。
-
未初始化数据区(BSS段):存储未初始化的全局变量和静态变量。
-
-
生命周期贯穿整个程序运行期间。
-
-
示例:
int globalVar = 10; // 全局变量,存储在已初始化数据区 static int staticVar; // 静态变量,存储在BSS段
4. 常量存储区(Constant Storage)
-
用途:用于存储字符串常量和其他常量数据。
-
特点:
-
数据在程序运行期间不可修改。
-
通常与代码段放在一起。
-
-
生命周期:整个程序运行期间。
-
示例:
const char *str = "Hello, World!"; // 字符串常量存储在常量区
5. 代码区(Text Segment)
-
用途:存储程序的执行代码(编译后的机器指令)。
-
特点:
-
只读,不可修改。
-
通常与常量存储区放在一起。
-
-
生命周期:整个程序运行期间。
内存布局总结
典型的C程序内存布局如下:
内存区域 | 存储内容 | 特点 |
---|---|---|
栈(Stack) | 局部变量、函数参数、返回地址等 | 自动管理,速度快,空间有限 |
堆(Heap) | 动态分配的内存 | 手动管理,空间大,速度较慢 |
全局/静态存储区 | 全局变量、静态变量 | 生命周期长,分为已初始化和BSS段 |
常量存储区 | 字符串常量、常量数据 | 只读,不可修改 |
代码区 | 程序的执行代码 | 只读,存储机器指令 |
示例代码
#include <stdio.h>
#include <stdlib.h>
int globalVar = 10; // 全局变量,存储在全局/静态存储区
static int staticVar; // 静态变量,存储在BSS段
void func() {
int localVar = 20; // 局部变量,存储在栈上
int *heapVar = (int *)malloc(sizeof(int)); // 动态分配,存储在堆上
*heapVar = 30;
printf("Local: %d, Heap: %d\n", localVar, *heapVar);
free(heapVar); // 手动释放堆内存
}
int main() {
const char *str = "Hello"; // 字符串常量,存储在常量区
func();
return 0;
}
总结
C语言中的内存分为栈空间、堆空间、全局/静态存储区、常量存储区和代码区。每种空间有不同的用途、特点和生命周期:
-
栈:自动管理,速度快,适合局部变量。
-
堆:手动管理,适合动态内存分配。
-
全局/静态存储区:存储全局和静态变量,生命周期长。
-
常量存储区:存储常量数据,不可修改。
-
代码区:存储程序的执行代码。