C语言中各种变量的内存分布

我来帮你梳理一下C语言中各种变量的内存分布,用个形象的比喻和总结让你再也不混淆。

一、内存布局图(先看全貌)

内存地址(高地址) ──┐

栈 (Stack)

↓ 生长

├───

堆 (Heap)

↑ 生长

├───

BSS段 (未初始化)

Data段 (已初始化)

Text段 (代码)

内存地址(低地址) ──┘

二、分门别类说清楚

  1. 全局变量

int global_var; // 未初始化全局变量

int global_init = 10; // 已初始化全局变量

未初始化全局变量 → BSS段

程序启动时自动清零

不占可执行文件空间

已初始化全局变量 → Data段

初始值保存在可执行文件中

程序加载时读入内存

  1. static全局变量

static int static_global; // 在BSS段

static int static_global2 = 20; // 在Data段

内存位置同普通全局变量

区别:作用域限于当前文件

记忆:static只改作用域,不改存储位置

  1. static局部变量

void func() {

static int static_local; // 在BSS段

static int static_local2 = 30; // 在Data段

}

同样在Data/BSS段

区别:只在第一次执行时初始化

作用域是函数内,但生命周期是全局

  1. 局部变量(非static)

void func() {

int local_var; // 在栈上

int local2 = 40; // 在栈上

}

都在栈(Stack)上

函数返回时自动释放

生存期 = 函数执行期间

  1. 动态分配内存

int *p = malloc(100); // 在堆(Heap)上

由程序员手动管理

malloc/new在堆上分配

需要free/delete释放

三、快速记忆口诀

口诀1:看三要素

  1. 作用域(哪里能用)

  2. 生存期(活多久)

  3. 存储位置(住哪里)

口诀2:位置判断

  • 有static → Data/BSS(看是否初始化)

  • 无static且在函数内 → 栈

  • 无static且在函数外 → Data/BSS

  • malloc/free → 堆

口诀3:初始值

  • 已初始化 → Data段

  • 未初始化 → BSS段(自动清零)

  • 局部变量(栈上)初始值随机!

四、实战代码示例

#include <stdio.h>

#include <stdlib.h>

// 全局变量

int g_uninit; // BSS段

int g_init = 100; // Data段

// static全局变量

static int sg_uninit; // BSS段

static int sg_init = 200; // Data段

void test() {

// 局部变量

int local = 10; // 栈

int local_uninit; // 栈(值随机!)

// static局部变量

static int sl_uninit; // BSS段

static int sl_init = 300; // Data段(只初始化一次!)

// 动态分配

int *heap_var = malloc(sizeof(int)); // 堆

*heap_var = 400;

printf("栈变量: %d\n", local);

printf("堆变量: %d\n", *heap_var);

printf("static局部: %d (下次调用会累加)\n", ++sl_init);

free(heap_var);

}

int main() {

printf("全局未初始化: %d (自动为0)\n", g_uninit);

printf("全局已初始化: %d\n", g_init);

test();

test(); // 第二次调用,static局部变量会保持值

return 0;

}

五、常犯错误提醒

⚠️ 注意这些坑:

栈变量不能返回地址

int* bad_func() {

int local = 10;

return &local; // 错误!函数结束栈就释放了

}

static局部变量只初始化一次

void counter() {

static int count = 0; // 这行只执行一次!

count++;

}

未初始化的栈变量值是随机的

void danger() {

int x; // 值不确定!

printf("%d", x); // 可能崩溃

}

六、一张表总结

|---|---|---|---|---|
| 变量类型 |||||
| 存储位置作用域生命周期初始值全局已初始化 |||||
| Data段整个程序程序运行期指定值全局未初始化 |||||
| BSS段整个程序程序运行期自动清零static全局 |||||
| Data/BSS当前文件程序运行期同上static局部 |||||
| Data/BSS函数内程序运行期同上普通局部 |||||
| 栈(Stack)函数内函数执行期随机值动态分配 |||||

堆(Heap)由指针决定直到free程序员控制终极记忆法:

有static或不在函数里 → Data/BSS(全局区域)

在函数里且没static → 栈

自己malloc的 → 堆

这样记是不是清楚多了?多用几次就形成肌肉记忆了!

相关推荐
网域小星球15 分钟前
C 语言从 0 入门(十四)|文件操作:读写文本、保存数据持久化
c语言·开发语言·文件操作·fopen·fprintf
网域小星球18 分钟前
C 语言从 0 入门(七)|字符数组与字符串完整精讲|VS2022 高质量实战
c语言·开发语言·字符串·vs2022·字符数组
Jia ming25 分钟前
C语言实现日期天数计算
c语言·开发语言·算法
浅时光_c2 小时前
12 指针
c语言·开发语言
爱编码的小八嘎2 小时前
C语言完美演绎7-11
c语言
爱编码的小八嘎2 小时前
C语言完美演绎7-9
c语言
范纹杉想快点毕业3 小时前
C语言全能实战教程
c语言·开发语言
ZK_H4 小时前
半导体工艺流程
java·c语言·开发语言·计算机网络·金融
网域小星球4 小时前
C语言从0入门(八)|函数基础:封装、调用与参数传递精讲
c语言·开发语言
网域小星球4 小时前
C语言从0入门(十)|二维数组详解与矩阵实战
c语言·算法·矩阵·二维数组·数组遍历