【问题标题】:Confusion in Structure Member Alignment结构成员对齐的混乱
【发布时间】:2012-08-07 00:06:06
【问题描述】:
typedef struct structc_tag
{
   char        c;
   double      d;
   int         s;
} structc_t;

我在一篇博客中读到这将占用 24 个字节的数据:

sizeof(char) + 7 字节填充 + sizeof(double) + sizeof(int) + 4 字节填充 = 1 + 7 + 8 + 4 + 4 = 24 字节。

我的问题是为什么要使用 7 字节的填充,为什么我们不能在那里使用 3 字节的填充并利用接下来的 8 字节进行加倍?最后 4 个字节需要什么?

【问题讨论】:

  • double 实体应与可被 8 整除的地址对齐,否则 FPU 在尝试从内存中加载值时可能会变得不高兴。在这种情况下必须发出非常慢的未对齐加载(并且某些平台根本不支持未对齐访问)。在 x64 CPU 上的 64 位模式下尤其如此,其中数学主要使用 SSE 完成。最后四个字节用于确保在一个接一个地堆叠许多此类结构时正确对齐(例如,在struct_t 的数组中)。
  • 通常很难确切知道结构或对象在实际实现中的大小,因为它在您使用的每个平台上都会发生变化。您通常应该只依靠编译器来尽其所能使用所需的字段并根据需要填充以获得最佳性能。这就是人们在检查对象使用的字节数时使用sizeof() 的原因——即使对于像 int 这样的原语也是如此。
  • 如果可以的话,只需根据字段的大小对字段进行排序,在您的情况下,这可能对大多数平台都有帮助

标签: c memory-management struct


【解决方案1】:

它取决于平台,但这取决于 double 与什么对齐。如果它对齐到 8 个字节,这似乎是这种情况,3 个字节的填充不会削减它。

如果double 对齐到 4 个字节,那么您是对的,将使用 3 个字节的填充。

【讨论】:

  • 对于 OP,您有时可以使用 pragma 覆盖默认对齐选项。例如对于 gcc,使用 #pragma pack(1) 来使用 1 字节对齐,#pragma pack(4) 等。你必须看看你的编译器支持什么。请注意,未对齐的内存访问可能比浪费空间并让编译器使用目标机器的首选对齐方式要慢得多。
【解决方案2】:

您需要考虑如果使用malloc() 分配这些结构的数组会发生什么:

structc_t *p = malloc(2 * sizeof *p);

考虑一个平台,其中sizeof(double) == 8sizeof(int) == 4double 所需的对齐方式为 8。malloc() 始终返回正确对齐的地址以存储任何 C 类型 - 所以在这种情况下 a 将为 8字节对齐。填充要求自然会消失:

  • 为了使a[0].d 8 字节对齐,因此a[0].c 之后必须有7 个字节的填充;

  • 为了使a[1].d 8 字节对齐,整体结构大小必须是8 的倍数,因此a[0].s 之后必须有4 个字节的填充。

    李>

如果您将struct 从大到小重新排序:

typedef struct structc_tag
{
   double      d;
   int         s;
   char        c;
} structc_t;

...那么唯一需要的填充是.c 之后的 3 个字节,以使结构大小成为 8 的倍数。这导致结构的总大小为 16,而不是 24。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多