实例1.全局变量2.字符串常量和数组3.静态变量4.局部变量5.动态申请的内存6. 函数代码小结实例#include stdio.h /************** 全局变量 **************/ // 已初始化全局变量 int g_init 100; // 未初始化全局变量 int g_uninit; // const 全局变量 const int g_const 200; // 字符串常量 char *g_str Hello World; // 全局数组 int g_array[5] {1, 2, 3, 4, 5}; /************** 函数 **************/ void func(void) { // 自动变量局部变量 int local 10; // 未初始化局部变量 int temp; // static局部变量已初始化 static int s_init 20; // static局部变量未初始化 static int s_uninit; // const局部变量 const int local_const 30; printf(%d %d %d %d %d\n, local, temp, s_init, s_uninit, local_const); s_init; } int main(void) { func(); int *p malloc(sizeof(int)); if (p ! NULL) { *p 100; printf(*p %d\n, *p); free(p); p NULL; } return 0; }1.全局变量对于已经初始化的全局变量显然需要记录下来所以放在.data 里面。对于未初始化的全局变量暂时不需要占用空间所以放入 .bss里面。对于const常量既然是只读的就放入 .rodata 。// 已初始化全局变量 int g_init 100; // 未初始化全局变量 int g_uninit; // const 全局变量 const int g_const 200;对象生命周期存储区域原因g_init整个程序.data已初始化全局变量g_uninit整个程序.bss未初始化全局变量g_const整个程序.rodata全局const只读数据2.字符串常量和数组字符串常量分为两个部分 g_str 是全局变量本身可以被修改也初始化了所以放在 .data 里面。“Hello World”是字符串常量放在 .rodatag_array是数组需要分配内存空间存放{1,2,3,4,5},// 字符串常量 char *g_str Hello World; // 全局数组 int g_array[5] {1, 2, 3, 4, 5};对象生命周期存储区域原因Hello World整个程序.rodata字符串常量g_str整个程序.data指针变量本身可修改g_array整个程序.data已初始化数组3.静态变量静态变量和全局变量很像如果是已经初始化了就放在 .data 段里面如果没有初始化就放在 .bss里面。// static局部变量已初始化 static int s_init 20; // static局部变量未初始化 static int s_uninit;对象生命周期存储区域原因s_init整个程序.datastatic且已初始化s_uninit整个程序.bssstatic未初始化4.局部变量// 自动变量局部变量 int local 10; // 未初始化局部变量 int temp; // const局部变量 const int local_const 30;对象生命周期存储区域原因local函数调用期间栈(Stack)自动变量temp函数调用期间栈(Stack)自动变量local_const函数调用期间栈通常生命周期仍属于局部变量程序未执行到该函数时local只有符号意义编译器知道有这个变量没有运行时内存。进入函数后在栈上分配空间local才真正存在。函数返回后栈空间被释放local的生命周期结束原来的内存可能还保留旧数据但已经不再属于它。局部变量并没有固定存放在栈中而是在函数执行期间由编译器生成的代码在栈上动态申请一块空间来存放它。5.动态申请的内存int *p malloc(sizeof(int)); *p 100;对象生命周期存储区域原因p函数调用期间栈(Stack)自动变量malloc(sizeof(int));100函数调用期间堆(Stack)动态申请出的内存Stack Heap --------------------- -------------- | p (地址0x1000) | --- | int 100 | --------------------- --------------6. 函数代码void func(void) { } int main(void) { }对象生命周期存储区域原因func()整个程序.text函数代码main()整个程序.text函数代码思考 是func 函数名在text还是整个void func(void){} 函数内容都在 text✅void func(void){...}编译后的所有机器指令都位于.text段。✅func这个名字本身不在.text它只是符号表Symbol Table中的一个符号指向.text中函数入口地址。func只是一个标签Label。它表示func ↓ 0x401120例如.text 地址 内容 ------------------------- 0x401120 func: 0x401120 push rbp 0x401121 mov rbp,rsp ... 0x401145 retCPU根本不知道func 这个名字CPU只知道call 0x401120小结高地址 ------------------------------- | Stack | |-------------------------------| | local | | p (保存堆内存地址) | ------------------------------- ↓ ------------------------------- | Heap | |-------------------------------| | malloc申请的int (100) | ------------------------------- ↓ ------------------------------- | BSS | |-------------------------------| | g_uninit | | s_uninit | ------------------------------- ------------------------------- | DATA | |-------------------------------| | g_init | | s_init | | g_array | | g_str指针 | ------------------------------- ------------------------------- | RODATA | |-------------------------------| | Hello World | | g_const | ------------------------------- ------------------------------- | TEXT | |-------------------------------| | main() | | func() | ------------------------------- 低地址