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的 → 堆

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

相关推荐
wangjialelele3 小时前
平衡二叉搜索树:AVL树和红黑树
java·c语言·开发语言·数据结构·c++·算法·深度优先
森G4 小时前
七、04ledc-sdk--------makefile有变化
linux·c语言·arm开发·c++·ubuntu
weixin_395448914 小时前
mult_yolov5_post_copy.c_cursor_0205
c语言·python·yolo
Z9fish5 小时前
sse哈工大C语言编程练习20
c语言·开发语言·算法
晓13135 小时前
第六章 【C语言篇:结构体&位运算】 结构体、位运算全面解析
c语言·算法
梵刹古音5 小时前
【C语言】 指针与数据结构操作
c语言·数据结构·算法
刘琦沛在进步6 小时前
【C / C++】引用和函数重载的介绍
c语言·开发语言·c++
VekiSon7 小时前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
2的n次方_8 小时前
CANN Ascend C 编程语言深度解析:异构并行架构、显式存储层级与指令级精细化控制机制
c语言·开发语言·架构
_F_y8 小时前
C语言重点知识总结(含KMP详细讲解)
c语言·开发语言