C 为什么&;第二个_变量的地址高于&;第一个变量?

C 为什么&;第二个_变量的地址高于&;第一个变量?,c,gcc,stack,C,Gcc,Stack,我有以下代码 int main(int argc, char *argv[]) { int value1 = 10; int value2 = 11; return 0; } 调试代码时,&value2高于&value1。这意味着value2首先被推送到堆栈,然后是value1 这是gcc的正常行为吗 为什么gcc自下而上编译变量 叮当声也有同样的表现吗 多亏了堆栈上局部变量的顺序完全依赖于实现,并且不需要看起来一致 使用gcc 4.8.5编译并运行上述代码时,val

我有以下代码

int main(int argc, char *argv[]) {
    int value1 = 10;
    int value2 = 11;

    return 0;
}
调试代码时,&value2高于&value1。这意味着value2首先被推送到堆栈,然后是value1

这是gcc的正常行为吗

为什么gcc自下而上编译变量

叮当声也有同样的表现吗


多亏了

堆栈上局部变量的顺序完全依赖于实现,并且不需要看起来一致

使用gcc 4.8.5编译并运行上述代码时,
value1
的地址高于
value2
,这与您看到的相反

我还尝试在gdb中运行此功能:

int main(int argc, char *argv[]) {
    int value1 = 10;
    int x = 4;
    int value2 = 11;

    printf("&1=%p, &2=%p\n", &value1, &value2);
    return 0;
}
得到这个:

(gdb)启动
0x40053c处的临时断点1:文件x1.c,第6行。
启动程序:/home/dbush//x1
x1.c处的临时断点1,main(argc=1,argv=0x7fffffe008):6
6整数值1=10;
缺少单独的调试信息,请使用:debuginfo安装glibc-2.17-196.el7.x86_64
(gdb)步骤
7 int x=4;
(gdb)
8整数值2=11;
(gdb)
10 printf(&1=%p,&2=%p\n“,&value1,&value2);
(gdb)p&value1
$1=(int*)0x7fffffffdf18
(gdb)p&value2
$2=(整数*)0x7FFFFFDF14
(gdb)p&x
$3=(整数*)0x7FFFFFFF1C
(gdb)
在这种情况下,
x
的地址位于
value1
value2
之后,即使它们之间定义了地址


这表明,您不能对堆栈上变量的顺序做出任何假设。

堆栈上局部变量的顺序完全依赖于实现,不需要看起来一致

使用gcc 4.8.5编译并运行上述代码时,
value1
的地址高于
value2
,这与您看到的相反

我还尝试在gdb中运行此功能:

int main(int argc, char *argv[]) {
    int value1 = 10;
    int x = 4;
    int value2 = 11;

    printf("&1=%p, &2=%p\n", &value1, &value2);
    return 0;
}
得到这个:

(gdb)启动
0x40053c处的临时断点1:文件x1.c,第6行。
启动程序:/home/dbush//x1
x1.c处的临时断点1,main(argc=1,argv=0x7fffffe008):6
6整数值1=10;
缺少单独的调试信息,请使用:debuginfo安装glibc-2.17-196.el7.x86_64
(gdb)步骤
7 int x=4;
(gdb)
8整数值2=11;
(gdb)
10 printf(&1=%p,&2=%p\n“,&value1,&value2);
(gdb)p&value1
$1=(int*)0x7fffffffdf18
(gdb)p&value2
$2=(整数*)0x7FFFFFDF14
(gdb)p&x
$3=(整数*)0x7FFFFFFF1C
(gdb)
在这种情况下,
x
的地址位于
value1
value2
之后,即使它们之间定义了地址


这表明您不能对堆栈上变量的顺序做出任何假设。

C语言标准没有在内存中强加任何特定的顺序。这适用于静态存储中的变量(如编译单元本地的全局变量、函数和变量或函数中的本地静态变量),也适用于堆上的变量(使用
malloc
等进行分配),以及堆栈上分配的局部变量

在特定情况下,编译器可能根本不分配任何内存(甚至不在处理器寄存器中),因为变量从未使用过。因此,例如,当您在启用优化的情况下编译时(
-O2
),变量将被优化掉,并且它们不会出现在生成的代码中

变量的位置是由定位器确定的,对于GNU工具,它是
ld
,这个链接器+定位器。这反过来又由链接器描述文件指导。因此,如果需要静态存储中的特定顺序或变量,可以通过自定义链接器描述文件来实现


但是,对于局部变量,位置是未指定的(由于编译器甚至没有指定将这些变量放置在何处,因此它甚至没有定义实现):这些变量可能会被放置在堆栈上,然后在寄存器中保留一段时间;或者,它们可以被完全优化。

C语言标准不会在内存中强加任何特定的顺序。这适用于静态存储中的变量(如编译单元本地的全局变量、函数和变量或函数中的本地静态变量),也适用于堆上的变量(使用
malloc
等进行分配),以及堆栈上分配的局部变量

在特定情况下,编译器可能根本不分配任何内存(甚至不在处理器寄存器中),因为变量从未使用过。因此,例如,当您在启用优化的情况下编译时(
-O2
),变量将被优化掉,并且它们不会出现在生成的代码中

变量的位置是由定位器确定的,对于GNU工具,它是
ld
,这个链接器+定位器。这反过来又由链接器描述文件指导。因此,如果需要静态存储中的特定顺序或变量,可以通过自定义链接器描述文件来实现


但是,对于局部变量,位置是未指定的(由于编译器甚至没有指定将这些变量放置在何处,因此它甚至没有定义实现):这些变量可能会被放置在堆栈上,然后在寄存器中保留一段时间;或者它们可能会被完全优化。

在您调试的架构上,堆栈会向后增长。我使用的是linux ubuntu,所以这是特定于ubuntu的?当我查看程序集时,值1首先被分配一个堆栈,但距离基指针最远。我认为这对ubuntu来说是正常的?堆栈的增长方向与局部变量的分配方式无关。几乎可以肯定,
value1
value2
的空间是同时分配的,方法是将堆栈指针调整为
2*sizeof(int)
字节,再加上编译器定义的簿记空间(返回地址等)。选择如何相对分配局部变量