C语言声明数组时的栈内存布局及数组索引存储顺序问题
C语言局部变量栈布局与数组存储顺序解答
注意:以下结论基于x86/x86_64、ARM等主流硬件架构,GCC、Clang、MSVC等主流编译器无优化、未开启栈保护(如Canary)的默认场景,C语言标准本身未对栈生长方向、局部变量分配顺序做强制规定,实际场景可能存在差异。
1. 基础规则说明
- 主流架构的栈默认从高内存地址向低内存地址生长:函数进入时栈指针向低地址偏移预留局部变量空间,先声明的局部变量通常分配在更高的内存地址。
- C语言数组的元素存储遵循下标越低、地址越低的规则:即任意数组
arr,都满足&arr[0] < &arr[1] < ... < &arr[n-1]。
2. 第一段代码的栈布局
第一段代码:
int main() { int a = 0; char b[8]; char c[8]; }
从高地址到低地址的内存布局顺序和你理解的一致,依次为:
- 4字节int变量
a(最高地址) - 8字节char数组
b:b[7]位于b的最高地址端,靠近a;b[0]位于b的最低地址端 - 8字节char数组
c(最低地址):c[7]位于c的最高地址端,靠近b;c[0]位于c的最低地址端
如果对c做越界写,溢出的内容会先覆盖b数组,继续溢出会覆盖a变量。
3. 第二段代码的数组索引顺序问题
第二段代码(补全语法后):
int main() { int a = 0; int b[8]; char c[8]; }
从高地址到低地址的内存布局顺序和你猜测的一致:
- 4字节int变量
a(最高地址) - 32字节int数组
b(8个元素每个占4字节) - 8字节char数组
c(最低地址)
你关注的数组索引和a的距离问题:
因为数组元素地址随索引递增而升高,b[7]是b数组中地址最高的元素,b[7]的地址更靠近a的内存地址,b[0]是b数组中地址最低的元素,更靠近c的内存地址。
如果对c做越界写,溢出内容会先覆盖b[0],再依次覆盖b[1]到b[7],继续溢出才会覆盖a变量。
内容的提问来源于stack exchange,提问作者Jhanikh
相关产品推荐
相关产品推荐

