为了账号安全,请及时绑定邮箱和手机立即绑定

堆栈上的局部变量分配顺序

堆栈上的局部变量分配顺序

C
互换的青春 2019-07-31 09:24:07
堆栈上的局部变量分配顺序看看这两个功能:void function1() {     int x;     int y;     int z;     int *ret;}void function2() {     char buffer1[4];     char buffer2[4];     char buffer3[4];     int *ret;}如果我打破function1()了gdb,并打印变量的地址,我得到这个:(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
查看完整描述

3 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

我不知道为什么GCC按照它的方式组织它的堆栈(虽然我猜你可以破解它的源或本文并找出),但是我可以告诉你如何保证特定堆栈变量的顺序如果由于某种原因你需要。简单地将它们放在一个结构中:

void function1() {
    struct {
        int x;
        int y;
        int z;
        int *ret;
    } locals;}

如果我的记忆正确地为我服务,spec保证&ret > &z > &y > &x。我离开了我的K&R工作,所以我不能引用章节和诗句。


查看完整回答
反对 回复 2019-07-31
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

所以,我做了一些实验,这就是我发现的。它似乎是基于每个变量是否是一个数组。鉴于此输入:

void f5() {
        int w;
        int x[1];
        int *ret;
        int y;
        int z[1];}

我最终在gdb中得到了这个:

(gdb) p &w
$1 = (int *) 0xbffff4c4(gdb) p &x
$2 = (int (*)[1]) 0xbffff4c0(gdb) p &ret 
$3 = (int **) 0xbffff4c8(gdb) p &y
$4 = (int *) 0xbffff4cc(gdb) p &z
$5 = (int (*)[1]) 0xbffff4bc

在这种情况下,ints和指针首先处理,最后在堆栈顶部声明,然后首先声明更接近底部。然后以相反的方向处理数组,声明越早,堆栈中的最高位。我确信这是有充分理由的。我不知道它是什么。


查看完整回答
反对 回复 2019-07-31
?
繁花如伊

TA贡献2012条经验 获得超12个赞

ISO C不仅没有说明堆栈上局部变量的排序,它甚至不能保证堆栈甚至存在。该标准只讨论了块内变量的范围和生命周期。


查看完整回答
反对 回复 2019-07-31
  • 3 回答
  • 0 关注
  • 500 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信