【问题标题】:Local Variables Alignment in C codeC 代码中的局部变量对齐
【发布时间】:2023-03-26 16:23:01
【问题描述】:

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

#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;
}

在我上面的程序中,我有 2 个结构变量和 1 个整数。 GCC 编译器决定分配这样的地址:

&i          0x00007FFFFFFFDF0C
&myStruct1  0x00007FFFFFFFDF10
&myStruct2  0x00007FFFFFFFDF20

结构内没有填充 - 结构的大小为 6 个字节。

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

【问题讨论】:

  • @user3629249 但我不确定你所说的是否解释了为什么 &myStruct2 没有在 &myStruct1 之后立即启动(地址:0x00007FFFFFFFDF16)
  • 结构的对齐方式取决于几个因素,例如#pragma 包、底层架构总线宽度、结构的任何成员所需的最大对齐方式、传递(或未传递)到的某些参数编译器、可寻址数据大小/对齐方式等。

标签: c struct stack padding


【解决方案1】:

在您的代码中,myStruct1myStruct2 是两个局部变量,它们的地址不需要相邻。 GCC 将它们这样放置是完全合法的。

比较一下:

struct s myStruct[2];

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

【讨论】:

  • 这之间的内存会发生什么 - 如果有大量这样的变量,那不是不会被使用,因此会膨胀堆栈帧的大小吗?也许堆栈在桌面世界中很少考虑,但在堆栈大小非常有限的嵌入式系统中呢?
  • 观察到 int 和 struct 变量是连续的,但 2 struct 变量不是,我更加怀疑
  • @NikhilJagdale 这不太可能是堆栈溢出的原因,编码错误是。 GCC 所做的事情是合法的,除非你有一些真实的证据表明它造成了问题,就是这样。
  • @YuHao @Electrix Padding 也适用于自变量。请参阅The Lost Art of Structure Packing。在您的情况下,struct s 的对齐方式为2,其大小为6,您可以通过alignofsizeof 进行调查。所以myStruct1myStruct2 位于可以被2 整除的任何地址。所以,最后不需要在struct st 内部填充,因为它的第一个成员(因此下一个struct st)可以是自动被2 整除的任何地址。
  • 注意:作为局部变量,它们的对齐方式是不可预测的,因为我们无法知道它们在机器字中是如何放置的。如果myStruct1 放在一个字尾,myStruct2 放在另一个字尾,则无需填充任何字节!我们还应该关心缓存行的宽度。在您的情况下,两个 struct ss 之间有 10(0x16 ~ 0x1f) 字节填充。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多