C 堆栈指针

C 堆栈指针,c,assembly,x86,C,Assembly,X86,考虑一个计划: #include <stdio.h> void function(int a, int b, int c){ char buffer1[5]; char buffer2[10]; } void main(){ function(1,2,3); } 考虑同一程序的另一个变体: #include <stdio.h> void function(int a, int b, int c){ char buff

考虑一个计划:

#include <stdio.h>

void function(int a, int b, int c){
    char buffer1[5];
    char buffer2[10];
}

void main(){
        function(1,2,3);
}
考虑同一程序的另一个变体:

#include <stdio.h>

void function(int a, int b, int c){
        char buffer1[7];
        char buffer2[10];
}

void main(){
        function(1,2,3);
}
我的问题是,是什么导致堆栈指针在第一种情况下递减16,在第二种情况下递减32,而在第二种情况下只需要再递减2个字节

我在英特尔处理器上运行64位Ubuntu14.04,来自:

-mprefered堆栈边界
=num
尝试使堆栈边界与提升为num字节的2边界对齐。如果未指定
-mprefered stack boundary
默认值为4(16字节或128位),优化代码大小(
-Os
)时除外,在这种情况下,默认值为最小正确对齐(x86为4字节,x86-64为8字节)


因此,当在堆栈上为数组分配空间时,堆栈也将在默认的16字节边界上对齐。在第一种情况下,您有15个字节的数据小于16,因此分配了16个字节。在第二种情况下,有17个字节的数据大于16但小于(16的下一个倍数)32,因此分配了32个字节的空间。

看起来像堆栈对齐。ceil(log2(15))==4,2^4==16。ceil(log2(17))==5,和2^5==32。我不明白这个谜是什么。这不是很明显吗?了解您的期望或您想要解释的内容将非常有帮助。@DavidSchwartz我想他只是在解释为什么要多使用16个字节的堆栈空间,而实际上只需要多使用2个字节。@MichaelWalz所以我们有三种可能的解读他的问题!这种一致性有什么重要性?我的意思是,编译器为什么要费心进行这种对齐?AFAIK GCC这样做是为了能够在堆栈上存储SSE数据,因为某些SSE指令有对齐要求。@Siddhant,@Michael:不仅仅是SSE。在x86中,未对齐的读/写速度较慢。在ARM(和许多其他体系结构)中,情况更糟:它会使程序崩溃(通常是通过总线错误)。除了效率之外,您还会发现,对操作系统上的标准库的调用约定将强制执行这一点。
#include <stdio.h>

void function(int a, int b, int c){
        char buffer1[7];
        char buffer2[10];
}

void main(){
        function(1,2,3);
}
void function(int a, int b, int c){
 80483ed:       55                      push   %ebp
 80483ee:       89 e5                   mov    %esp,%ebp
 80483f0:       83 ec 20                sub    $0x20,%esp
        char buffer1[7];
        char buffer2[10];
}