好的,这里为你做一个精简版的总结,让你快速抓住C语言内存模型的要点:
C语言内存主要分区及其特点:
栈 (Stack) 区:
- 放什么: 函数的局部变量、函数参数、函数调用的返回地址等。
- 谁管: 编译器自动分配和释放。
- 特点: 速度快,但空间有限。函数调用结束,里面东西就没了(“先进后出,后进先出”)。
- 例子:
void func() { int x = 10; }
(x
就在栈上)
堆 (Heap) 区:
- 放什么: 程序运行时动态申请的内存(比如用
malloc
、calloc
申请的)。 - 谁管: 程序员手动申请 (
malloc
) 和释放 (free
)。 - 特点: 空间大,灵活,但分配/释放较慢。忘了
free
就会内存泄漏。 - 例子:
char *p = (char*)malloc(100);
(p
指向的100字节在堆上,p
本身可能在栈或静态区)
- 放什么: 程序运行时动态申请的内存(比如用
静态存储区 (Static/Global Storage Area):
- 放什么: 全局变量、静态变量 (
static
修饰的变量,无论全局还是局部)。 - 谁管: 程序启动时分配,程序结束时由系统释放。
- 特点: 整个程序运行期间都存在。
- 细分:
- 数据段 (.data): 存放已初始化的全局变量和静态变量。
- BSS 段 (.bss): 存放未初始化的全局变量和静态变量 (系统会自动给它们赋零值或空指针)。
- 例子:
int global_var = 1; static int static_var = 2;
- 放什么: 全局变量、静态变量 (
常量存储区 (Constant Storage Area / .rodata):
- 放什么: 字符串字面量 (如
"hello world"
)、用const
修饰的全局变量 (通常情况下)。 - 谁管: 程序启动时分配,程序结束时释放。
- 特点: 通常是只读的,内容在程序运行期间不能修改。
- 例子:
const char *message = "Hello";
("Hello"
在这里)
- 放什么: 字符串字面量 (如
代码区 (Code Segment / .text):
- 放什么: 程序的二进制机器指令。
- 谁管: 操作系统。
- 特点: 只读,可共享。
关键点回顾 (针对你的例子):
char *fun1() { char *str = "hello"; return str; }
"hello"
:在 常量区。str
(指针变量本身):在 栈区 (函数执行完就没了)。- 返回安全:因为
"hello"
一直在,返回的地址有效。
char *fun2() { char str[] = "hello"; return str; }
str
(数组内容 "hello"):在 栈区 (函数执行完就没了)。- 返回危险:因为数组
str
的内存会在函数返回后被回收,返回的地址指向一块无效的内存。
char *fun2_static() { static char str[] = "hello"; return str; }
str
(数组内容 "hello"):在 静态存储区 (程序运行期间一直有效)。- 返回安全:因为
str
数组的内存一直存在。
一句话概括:
- 栈:临时工,干完活就走人,东西也带走。
- 堆:租来的仓库,自己管钥匙,用完得自己还,忘了还就一直占着。
- 静态/全局区:公司的固定资产,从开张到倒闭都在。
- 常量区:刻在石头上的规章制度,只能看不能改。
希望这个总结能帮你快速理解!