【发布时间】:2010-11-09 06:40:58
【问题描述】:
看看这两个函数:
void function1() {
int x;
int y;
int z;
int *ret;
}
void function2() {
char buffer1[4];
char buffer2[4];
char buffer3[4];
int *ret;
}
如果我在gdb 中的function1() 中断,并打印变量的地址,我会得到:
(gdb) p &x
$1 = (int *) 0xbffff380
(gdb) p &y
$2 = (int *) 0xbffff384
(gdb) p &z
$3 = (int *) 0xbffff388
(gdb) p &ret
$4 = (int **) 0xbffff38c
如果我在 function2() 做同样的事情,我会得到:
(gdb) p &buffer1
$1 = (char (*)[4]) 0xbffff388
(gdb) p &buffer2
$2 = (char (*)[4]) 0xbffff384
(gdb) p &buffer3
$3 = (char (*)[4]) 0xbffff380
(gdb) p &ret
$4 = (int **) 0xbffff38c
您会注意到,在这两个函数中,ret 存储在最靠近堆栈顶部的位置。在function1() 中,紧随其后的是z、y,最后是x。在function2() 中,ret 后面是 buffer1,然后是 buffer2 和 buffer3。为什么存储顺序会改变?我们在两种情况下都使用了相同数量的内存(4 字节 ints 与 4 字节 char 数组),所以这不是填充问题。这种重新排序可能有什么原因,此外,是否可以通过查看 C 代码提前确定局部变量的排序方式?
现在我知道 C 的 ANSI 规范没有说明局部变量的存储顺序,并且允许编译器选择自己的顺序,但我想编译器有关于它如何存储的规则会处理这个问题,并解释为什么这些规则是这样的。
作为参考,我在 Mac OS 10.5.7 上使用 GCC 4.0.1
【问题讨论】:
-
重要吗?需要在特定地址分配变量吗?
-
不,这不重要,只是一个学术练习。
-
优化程度会影响答案吗?纯粹的猜测,但也许没有优化/低优化,int 是寄存器分配的候选对象,但 char[4] 不是,并且由于它们的处理方式不同,这两种机制恰好以不同的顺序将它们放在堆栈上。即使优化没有任何区别,但处理自动值的方式中的其他东西意味着 int 总是走一条路线,而数组总是走另一条路线,这似乎是合理的。