c - 这些局部变量的地址背后的基本原理是什么?
问题描述
我正在玩耍并查看内存中的局部变量。令我惊讶的是,我不明白为什么地址是这样的。
这是示例程序
int main() {
int my_array[30];
int a = 10;
int b = 11;
char h = 'A';
char temp_array[10];
int c = 12;
}
我希望堆栈框架按顺序排列所有这些变量。在 GDB 中打印出内存地址表明情况并非如此!
(gdb) print &my_array
$4 = (int (*)[30]) 0x7fffffffde10
(gdb) print &a
$5 = (int *) 0x7fffffffde04
(gdb) print &b
$6 = (int *) 0x7fffffffde08
(gdb) print &h
$7 = 0x7fffffffde03 '/' <repeats 13 times>
(gdb) print &temp_array
$8 = (char (*)[10]) 0x7fffffffde90
(gdb) print &c
$9 = (int *) 0x7fffffffde0c
基于这些内存地址,栈帧实际上是:
temp_array <--- Highest memory address
---------
my_array
---------
c
---------
b
---------
a
---------
h <---- Lowest memory address
为什么会这样?我假设我的编译器(gcc)以这种方式安排它是有原因的,有人可以告诉我为什么吗?谢谢你。编辑:可能是字节对齐还是什么?缓冲区先行,然后是整数,然后是字符,话虽这么说,那为什么要使用 CBA 而不是 ABC?
解决方案
为什么会这样?
编译器可以自由地布置它认为合适的堆栈帧。这种布局可以从版本到版本,从编译器到编译器,并且具有不同的优化级别。
要准确了解选择此特定布局的原因,您必须在 GCC 执行布局时单步执行。
一般来说,GCC 可能会尝试最小化变量之间的孔/填充(当他们的程序用完堆栈时它会惹恼最终用户)。这可以解释为什么所有int
变量都被分配在一起——它们具有相同的对齐要求,并且可以一个接一个地分配而没有间隙。
推荐阅读
- angular - 使用自定义搜索词过滤 RadListView
- dart - 如何使用 document.querySelector 使用 ngFor 更改 css 类?
- node.js - GeoFirestore 中的 set() 函数存在问题
- sql - SQL - 将所有用户联合在一个表中
- python - 在 Geopandas 中绘图时管理投影
- ios - textViewDidChange 仅在输入完整字符串时才会更改。我希望它检查每个字符
- c# - 具有多个可选参数调用不同操作的 Asp.net core 路由
- vim - VIM 使用 STDIN 中的语法高亮打开 YAML
- java - 如何创建有效的自定义 JSON 解析异常映射?
- excel - 使用 VBA 中的 CountA 和 Offset 在不断变化的工作表中插入数据验证