c语言中的函数参数对齐



过程中的数组破坏过程参数对齐。具有以下代码:

void _func(unsigned long cnt, int* adr, ...){
char a[1];
printf("cnt: %p, adr: %pn", &cnt, &adr);
}
int main(void){
_func(0, (int*)1, 2, 3, 4, 5);
return 0;
}

…用

编译gcc -m32 -O0 main.c

,输出如下:

cnt: 0xff911960, adr: 0xff91193c

是36 (0x24)字节的差异。问题是为什么它是什么?不应该是sizeof(cnt)吗?

但是如果我删除char a[1]或添加-O2标志,差异将是4字节(像往常一样)。

是什么导致了这种行为?

PS:在编译器资源管理器网站上,偏移量一直是4字节。

&cnt&adr为参数地址。形参是函数的局部变量,被初始化为调用者传递的实参值。编译器不需要使用与传递实参相同的形参空间。

当实参在堆栈上传递时,编译器可能会也可能不会为该形参重用其堆栈空间。当一个参数在处理器寄存器中传递,并且需要一个地址时,因为程序需要这个地址并输出它,那么编译器必须在堆栈上为参数预留空间,将值从寄存器复制到堆栈空间(就像存储指令一样),并使用堆栈空间的地址。

当编译器为此布局堆栈空间时,它不需要关心cntadr是连续的参数。它可以组织它所需的所有堆栈空间的数据——参数、局部变量、返回地址、它自己的目的,等等——然后按任何顺序为这些东西分配堆栈空间。所以你不应该期望cntadr的地址之间有任何密切的关系。

(对于具有可变参数的函数,编译器需要某种方式来实现可变参数列表特性。这通常涉及到在最后一个固定参数(在示例中是adr)之后在内存中连续放置变量参数。这并不意味着cntadr之间存在任何关系。

最新更新