栈从高地址到低地址分配内存

shihyuyao 2013-11-09 02:33:13
#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 地址还低?

谢谢
...全文
969 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-11-10
  • 打赏
  • 举报
回复
栈的生长方向,一般是由CPU确定的; 除非CPU不关心堆栈的生长方向,编译器才会自由安排。
mujiok2003 2013-11-09
  • 打赏
  • 举报
回复

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)
这个可以证明。
mujiok2003 2013-11-09
  • 打赏
  • 举报
回复
引用 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的栈是往低地址方向增长。注意,这个结论不能推广到其它编译器上。
忽略
mujiok2003 2013-11-09
  • 打赏
  • 举报
回复
$ 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的栈是往低地址方向增长。注意,这个结论不能推广到其它编译器上。
lm_whales 2013-11-09
  • 打赏
  • 举报
回复
栈从高地址到低地址分配内存 是自动变量,分配内存先后得到的地址的高低问题。 如果编译器按照,自动变量的定义顺序分配自动变量内存。 那么,先定义的地址高,后定义的地址低。 如果编译器,实现的,不是这种最自然的实现的方式, 而是另有安排; 就没有办法确定自动变量定义顺序, 和自动变量的内存地址的位置的关系了。 毕竟,编译后才确定地址 而不是一边编译,一边确定地址; 所以可以任意调整,只要不影响函数运行,就是对的。
derekrose 2013-11-09
  • 打赏
  • 举报
回复
问题和实验结果不矛盾啊
AnYidan 2013-11-09
  • 打赏
  • 举报
回复
如果lz的兴趣在 programming,暂时不要纠结与平台相关、实现相关的特性
max_min_ 2013-11-09
  • 打赏
  • 举报
回复
与程序本身无关,与你的环境密切相关!
CodefansZ 2013-11-09
  • 打赏
  • 举报
回复
引用 2 楼 Benjaminzhou93 的回复:
编译器相关,在vc6.0就完全是你想要的答案 测试了下,gcc把不同类型进行分区了struct < int < char
改正,gcc只把struct分为一类,int 和 char 是符合入桟顺序的另一类
nadleeh 2013-11-09
  • 打赏
  • 举报
回复
引用 楼主 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 地址还低? 谢谢
没有强制规定入栈顺序啊,除非哪些处理器的调用规范强制指定了。 过分强调入栈的顺序没有意义,变量无论怎么放,只要放的地址合法,并且有显示的返回变量返回的地址(首地址)程序就能够找到它(们)
CodefansZ 2013-11-09
  • 打赏
  • 举报
回复
编译器相关,在vc6.0就完全是你想要的答案 测试了下,gcc把不同类型进行分区了struct < int < char
自信男孩 2013-11-09
  • 打赏
  • 举报
回复
入栈顺序和函数内的变量申明顺序可能不一样, 这和编译器有一定的关系,所以不能通过一个函数内的多个变量在栈中的地址来判断栈的增长方向。 判断栈的增长方向可以使用多个函数调用,比如:A 函数调用B函数,B函数调用C函数,在A/B/C函数内部都定义一个变量(局部),然后分别打印其地址值(建议使用%p)。

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧