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

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

相关推荐
norlan_jame2 天前
C-PHY与D-PHY差异
c语言·开发语言
czy87874752 天前
除了结构体之外,C语言中还有哪些其他方式可以模拟C++的面向对象编程特性
c语言
m0_531237172 天前
C语言-数组练习进阶
c语言·开发语言·算法
Z9fish2 天前
sse哈工大C语言编程练习23
c语言·数据结构·算法
代码无bug抓狂人2 天前
C语言之单词方阵——深搜(很好的深搜例题)
c语言·开发语言·算法·深度优先
CodeJourney_J2 天前
从“Hello World“ 开始 C++
c语言·c++·学习
枫叶丹42 天前
【Qt开发】Qt界面优化(七)-> Qt样式表(QSS) 样式属性
c语言·开发语言·c++·qt
with-the-flow2 天前
从数学底层的底层原理来讲 random 的函数是怎么实现的
c语言·python·算法
Sunsets_Red2 天前
P8277 [USACO22OPEN] Up Down Subsequence P 题解
c语言·c++·算法·c#·学习方法·洛谷·信息学竞赛
小刘爱玩单片机2 天前
【stm32简单外设篇】- 测速传感器模块(光电)
c语言·stm32·单片机·嵌入式硬件