user-0 提问: 栈从高地址到低地址分配内存

回复:
user: user-1
content: 栈的生长方向，一般是由CPU确定的； 除非CPU不关心堆栈的生长方向，编译器才会自由安排。

user: user-2
content: Breakpoint 2, main () at test.s:35 35              call    _foo //调用函数foo (gdb) info reg eax            0x1      1 ecx            0x20018020       536969248 edx            0x0      0 ebx            0x22ac2c 2272300 esp            0x22abf0 0x22abf0  ebp            0x22ac08 0x22ac08 //esp < ebp， 说明是向低地址增长的 esi            0x0      0 edi            0x20039378       537105272 eip            0x40119d 0x40119d <main+21> eflags         0x246    [ PF ZF IF ] cs             0x1b     27 ss             0x23     35 ds             0x23     35 es             0x23     35 fs             0x3b     59 gs             0x0      0 (gdb) s foo () at test.s:8 8               pushl   %ebp //函数foo内部 (gdb) info reg eax            0x1      1 ecx            0x20018020       536969248 edx            0x0      0 ebx            0x22ac2c 2272300 esp            0x22abec 0x22abec  //esp 比调用函数前的值0x22abf0小了4,进一步证明栈是往低地址方向增长  ebp            0x22ac08 0x22ac08 esi            0x0      0 edi            0x20039378       537105272 eip            0x401180 0x401180 <foo> eflags         0x246    [ PF ZF IF ] cs             0x1b     27 ss             0x23     35 ds             0x23     35 es             0x23     35 fs             0x3b     59 gs             0x0      0 (gdb) n 11              movl    %esp, %ebp (gdb) info reg eax            0x1      1 ecx            0x20018020       536969248 edx            0x0      0 ebx            0x22ac2c 2272300 esp            0x22abe8 0x22abe8 //执行ebp入栈后，esp进一步减小4  ebp            0x22ac08 0x22ac08 esi            0x0      0 edi            0x20039378       537105272 eip            0x401181 0x401181 <foo+1> eflags         0x246    [ PF ZF IF ] cs             0x1b     27 ss             0x23     35 ds             0x23     35 es             0x23     35 fs             0x3b     59 gs             0x0      0 (gdb) f #0  foo () at test.s:11 11              movl    %esp, %ebp (gdb) bt #0  foo () at test.s:11 #1  0x004011a2 in main () at test.s:35 (gdb)    这个可以证明。

user: user-2
content: 引用 9 楼 mujiok2003 的回复:$ cat test.c; gcc -Wall test.c -o demo; ./demo #include <stdio.h>   int main() {     void* sp = 0;     //取出当前的栈顶指针     asm("movl %%esp,%0;"         :"=r"(sp)     );     printf("sp:%p\n", sp);      asm("push $0"); //整数0入栈     //取出当前的栈顶指针     asm("movl %%esp,%0;"         :"=r"(sp)     );     printf("sp:%p\n", sp);     //出栈     asm("pop %0"        :"=r"(sp)     );     return 0; }  //sp:0x22ac10 //sp:0x22ac0c   gcc 4.7.3，上面的例子可以说明GCC的栈是往低地址方向增长。注意，这个结论不能推广到其它编译器上。 忽略

user: user-2
content: $ cat test.c; gcc -Wall test.c -o demo; ./demo #include <stdio.h>   int main() {     void* sp = 0;     //取出当前的栈顶指针     asm("movl %%esp,%0;"         :"=r"(sp)     );     printf("sp:%p\n", sp);      asm("push $0"); //整数0入栈     //取出当前的栈顶指针     asm("movl %%esp,%0;"         :"=r"(sp)     );     printf("sp:%p\n", sp);     //出栈     asm("pop %0"        :"=r"(sp)     );     return 0; }  //sp:0x22ac10 //sp:0x22ac0c   gcc 4.7.3，上面的例子可以说明GCC的栈是往低地址方向增长。注意，这个结论不能推广到其它编译器上。

user: user-1
content: 栈从高地址到低地址分配内存 是自动变量，分配内存先后得到的地址的高低问题。  如果编译器按照，自动变量的定义顺序分配自动变量内存。 那么，先定义的地址高，后定义的地址低。  如果编译器，实现的，不是这种最自然的实现的方式， 而是另有安排； 就没有办法确定自动变量定义顺序， 和自动变量的内存地址的位置的关系了。  毕竟，编译后才确定地址 而不是一边编译，一边确定地址； 所以可以任意调整，只要不影响函数运行，就是对的。

user: user-3
content: 问题和实验结果不矛盾啊

user: user-4
content: 如果lz的兴趣在 programming，暂时不要纠结与平台相关、实现相关的特性

user: user-5
content: 与程序本身无关，与你的环境密切相关！

user: user-6
content: 引用 2 楼 Benjaminzhou93 的回复:编译器相关，在vc6.0就完全是你想要的答案 测试了下，gcc把不同类型进行分区了struct < int < char 改正，gcc只把struct分为一类，int 和 char 是符合入桟顺序的另一类

user: user-7
content: 引用 楼主 shihyuyao 的回复:#include <stdio.h>  struct S {     int a;     int b[20];     int c; };  int main(int argc, char *argv[]) {     struct S s, s1;     int a;     int b;      printf("%ld\n",(long int)&s);     printf("%ld\n",(long int)&s1);     printf("%ld\n",(long int)&a);     printf("%ld\n",(long int)&b);          return 0; }  140735395152864  // s 140735395152768   // s1 140735395152956  // a 140735395152952   // b   gcc4.3  为什么 s , s1 地址比 a , b 地址还低?   谢谢  没有强制规定入栈顺序啊，除非哪些处理器的调用规范强制指定了。 过分强调入栈的顺序没有意义，变量无论怎么放，只要放的地址合法，并且有显示的返回变量返回的地址（首地址）程序就能够找到它（们）

user: user-6
content: 编译器相关，在vc6.0就完全是你想要的答案 测试了下，gcc把不同类型进行分区了struct < int < char

user: user-8
content: 入栈顺序和函数内的变量申明顺序可能不一样， 这和编译器有一定的关系，所以不能通过一个函数内的多个变量在栈中的地址来判断栈的增长方向。 判断栈的增长方向可以使用多个函数调用，比如：A 函数调用B函数，B函数调用C函数，在A/B/C函数内部都定义一个变量（局部），然后分别打印其地址值（建议使用%p)。