C 中的函数参数对齐
Function arguments alignment in C
过程中断过程参数对齐中的数组。
有以下代码:
void _func(unsigned long cnt, int* adr, ...){
char a[1];
printf("cnt: %p, adr: %p\n", &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: 在compiler explorer网站上,偏移量一直是4字节。
&cnt
和&adr
是参数地址。参数是函数的局部变量,它们被初始化为调用者传递的参数值。编译器不需要对用于传递参数的参数使用相同的 space。
当参数在堆栈上传递时,编译器可能会也可能不会为参数重用其堆栈 space。当在处理器寄存器中传递参数并且需要地址时,因为程序获取地址并打印它,然后编译器必须为堆栈上的参数保留 space ,从中复制值寄存器到堆栈 space(与存储指令一样),并使用堆栈地址 space.
编译器在为此space布局栈时,不需要关心cnt
和adr
是连续的参数。它可以组织有关它需要的所有堆栈 space 的数据——用于参数、局部变量、return 地址、用于它自己的目的等等——然后只需将堆栈 space 分配给那些东西以任何顺序。所以你不应该期望 cnt
和 adr
.
的地址之间有任何密切的关系
(对于具有可变参数的函数,编译器需要以某种方式实现可变参数列表功能。这通常涉及在最后一个固定参数之后在内存中连续使用可变参数,这将是 adr
在例如。这不会在 cnt
和 adr
之间强加任何关系。)
过程中断过程参数对齐中的数组。 有以下代码:
void _func(unsigned long cnt, int* adr, ...){
char a[1];
printf("cnt: %p, adr: %p\n", &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: 在compiler explorer网站上,偏移量一直是4字节。
&cnt
和&adr
是参数地址。参数是函数的局部变量,它们被初始化为调用者传递的参数值。编译器不需要对用于传递参数的参数使用相同的 space。
当参数在堆栈上传递时,编译器可能会也可能不会为参数重用其堆栈 space。当在处理器寄存器中传递参数并且需要地址时,因为程序获取地址并打印它,然后编译器必须为堆栈上的参数保留 space ,从中复制值寄存器到堆栈 space(与存储指令一样),并使用堆栈地址 space.
编译器在为此space布局栈时,不需要关心cnt
和adr
是连续的参数。它可以组织有关它需要的所有堆栈 space 的数据——用于参数、局部变量、return 地址、用于它自己的目的等等——然后只需将堆栈 space 分配给那些东西以任何顺序。所以你不应该期望 cnt
和 adr
.
(对于具有可变参数的函数,编译器需要以某种方式实现可变参数列表功能。这通常涉及在最后一个固定参数之后在内存中连续使用可变参数,这将是 adr
在例如。这不会在 cnt
和 adr
之间强加任何关系。)