C代码中的局部变量对齐

C代码中的局部变量对齐,c,struct,stack,padding,C,Struct,Stack,Padding,我试图理解结构变量的打包是如何影响堆栈上局部变量的地址分配方式的 #include <stdio.h> struct s { short s1; short s2; short s3; }; int main() { struct s myStruct1; struct s myStruct2; myStruct1.s1 = 1; myStruct1.s2 = 2; myStruct1.s3 = 3; m

我试图理解结构变量的打包是如何影响堆栈上局部变量的地址分配方式的

#include <stdio.h>

struct s
{
    short s1;
    short s2;
    short s3;
};

int main()
{
    struct s myStruct1;
    struct s myStruct2;

    myStruct1.s1 = 1;
    myStruct1.s2 = 2;
    myStruct1.s3 = 3;

    myStruct2.s1 = 4;
    myStruct2.s2 = 5;
    myStruct2.s3 = 6;

    int i = 0xFF;

    printf("Size of struct s: %d", sizeof(myStruct1));
    return 0;
}
结构中没有填充-结构的大小为6字节


问题是为什么myStruct2位于2字节边界上,而它本可以放在myStruct1之后的6个字节上?

在您的代码中,
myStruct1
myStruct2
是两个局部变量,它们的地址不需要彼此相邻。GCC这样说是完全合法的

将其与此进行比较:

struct s myStruct[2];

myStruct[0]
myStruct[1]
必须相邻,因为它们在同一个数组中。

@user3629249但我不确定您所说的是否解释了为什么&myStruct2不能在&myStruct1之后立即启动(地址:0x00007FFFFFFFDF16)。结构的对齐取决于几个因素,如#pragma pack,底层架构总线宽度、结构的任何成员所需的最大对齐方式、传递(或未传递)给编译器的某些参数、可寻址数据大小/对齐方式,等等。中间的内存会发生什么情况?如果有大量这样的变量,内存不会被闲置,从而导致堆栈帧的大小膨胀吗?在桌面世界中,可能很少考虑堆栈,但是在堆栈大小非常有限的嵌入式系统中呢?我更怀疑的是,观察到int和struct变量是连续的,但2 struct变量是连续的arent@NikhilJagdale这不太可能是堆栈溢出的原因,编码错误是。GCC所做的是合法的,除非你有一些真实的证据表明它导致了问题,就是这样。@YuHao@Electrix Padding也适用于自变量。提到在您的例子中,
struct s
的对齐方式是
2
,它的大小是
6
,您可以通过
alignof
sizeof
来调查它们。因此
myStruct1
myStruct2
位于可被
2
整除的任何地址。因此,没有必要在末尾填充
struct st
,因为它的第一个成员(因此下一个
struct st
)可以是任何可以被
2
自动整除的地址。注意:作为局部变量,它们的对齐方式是不可预测的,因为我们不知道它们在机器字中的位置。如果
myStruct1
放在一个单词的末尾,而
myStruct2
放在另一个单词的末尾,则无需填充任何字节!我们还应该关心缓存线的宽度。在您的情况下,两个
结构之间有
10
0x16
~
0x1f
)字节填充。
struct s myStruct[2];