我的堆栈是向上而不是向下增长吗?

时间:2014-12-23 13:44:01

标签: c gcc

据我所知,堆栈假设向下增长。

我尝试运行此代码:

#include<stdio.h>

void func(char* a1, int a2, int a3) {

    char b1[10];
    int b2;
    int b3;

    printf("a3 address is: %p\n", &a3);
    printf("a2 address is: %p\n", &a2);
    printf("a1 address is: %p\n", &a1);
    printf("-----------------------\n");
    printf("b1 address is: %p\n", &b1);
    printf("b2 address is: %p\n", &b2);
    printf("b3 address is: %p\n", &b3);
}


int main() {
    func("string",2,3);
    return 0;
}

结果并不像我预期的那样:

a3 address is: 0x7fff68473190
a2 address is: 0x7fff68473194
a1 address is: 0x7fff68473198
-----------------------
b1 address is: 0x7fff684731b0
b2 address is: 0x7fff684731a8
b3 address is: 0x7fff684731ac

我不希望{I},b1b2按照我声明的方式进行排序。我知道编译器可能会更改该顺序以启用优化和对齐,但为什么堆栈似乎朝着高地址而不是低地址增长?

1 个答案:

答案 0 :(得分:4)

tl; dr使用您问题中的代码,我们无法分辨。

局部变量在堆栈中出现的顺序取决于编译器。它可能会重新排序,甚至可能不会为某些变量分配堆栈空间(因为它们已被优化掉,或者被分配给寄存器)。

函数参数的方式被推入堆栈 - 如果有的话! - 由您的平台ABI决定。在我的情况下(x86-64),三个参数在寄存器(%edi%esi%edx)中传递:

main:
        ...
        movl    $3, %edx
        movl    $2, %esi
        movl    $.LC7, %edi
        call    func

为了编译采用a1a2a3地址的代码,编译器必须不遗余力地将三个寄存器的值存储在什么是有效的三个未命名的局部变量:

func:
        ...
        movq    %rdi, -56(%rbp)
        movl    %esi, -60(%rbp)
        movl    %edx, -64(%rbp)

总之,您的问题中的代码不足以得出堆栈增长的方式。

幸运的是,我们先验地知道这种事情,或者可以使用不同的代码来解决这个问题:What is the direction of stack growth in most modern systems?