结构是否保证与C中的sizeof(size_t)对齐?

时间:2018-04-15 16:47:05

标签: c

我有以下结构:

struct data {
        char buffer[12];
        bool flag;
}

在测试data结构的大小时,我意识到它是16个字节,因为布尔标志在填充中添加了3个字节。所以我决定在使用buffer的最后一个字节作为标志时执行以下操作:

struct data {
        char buffer[16];
}

这样我的buffer可以免费增加3字节,因为无论如何它都会在填充中丢失。

但是,我希望这个结构与平台无关,所以我查看了cppreference和found the following(强调我的):

  

每个完整的对象类型都有一个称为对齐要求的属性,是一个size_t类型的整数值,表示连续地址之间的字节数,可以分配此类型的对象。

基于此,我写了以下内容:

struct data {
        char buffer[12 + sizeof(size_t)];
}

它可以在我的设备上运行,但我只是想知道是否可以保证在所有平台上正确对齐而不浪费任何字节?

编辑:我知道sizeof(size_t)可能是8个字节,使我的结构20字节。但是,如果对齐是8个字节,那么我的结构将是20个字节。这就是为什么我想知道结构是如何对齐的。

5 个答案:

答案 0 :(得分:3)

struct是否保证与C中的sizeof(size_t)对齐?

没有

我怀疑以下内容符合OP的访问padding的目标。会员订单很重要。最小的成员。 char总是最小的。

struct data_ref {
  bool flag;
  char buffer[12];
};

#define PAD (sizeof(struct data_ref) - sizeof(char)*12 - sizeof(bool))

struct data {
  bool flag;
  char buffer[12 + PAD];
};

答案 1 :(得分:1)

  

结构是否保证与C中的sizeof(size_t)对齐?

没有。他们为什么会这样?

答案 2 :(得分:1)

C标准没有规定struct内字段的对齐方式。 C standard states的第6.7.2.1节第14节:

  

结构或联合对象的每个非位字段成员都对齐   一种适合其类型的实现定义方式。

因此,不能保证给定的结构将以相同的方式布置在相同源代码的两个不同编译中,无论是不同的编译器还是具有不同优化设置的相同编译器。

作为一个反例,给出以下结构:

struct test1 {
    char s[13];
};

在我的计算机上,sizeof(struct test1)评估为13而_Alignof(struct test1)评估为1.事实上,我对struct data的第一个定义得到了相同的结果,表明其中有{&1}}。没有填充物。

因此无法保证结构在sizeof(size_t)边界上对齐。

关于你给出的引用:

  

每个完整的对象类型都有一个名为alignment的属性   requirement,是一个size_t类型的整数值,表示   连续地址之间的字节数   类型可以分配。

这表明所有类型都有对齐要求该值的类型为size_t,而不是类型必须有对齐那个sizeof(size_t)

话虽如此,有一种结构倾向于布局,并且如果遵循这些约定,通常可以减小结构的大小。

一般来说,结构的对齐要求最终是其字段的最大对齐要求,并且数组的对齐要求与其包含类型的对齐要求相同。此外,原始类型n字节的大小通常需要在n字节边界上对齐。因此,当结构中的字段具有不同的对齐要求时,通常会插入填充以确保满足每个字段的对齐要求。

对于你的结构,你有一个char数组,其元素大小为1,bool的大小(至少在我的机器上)也是1,所以结构整体对齐要求为1,不需要填充。

利用这些属性,通常可以减小结构的大小。 The Lost Art of Struct Packing更加详细地介绍了这一点。

重申一下,根据标准,结构中字段的布局方式是实现定义。因此,虽然可能能够布置结构以最小化填充,但仍然无法保证它在所有环境中始终都是相同的。

答案 3 :(得分:0)

  

结构是否保证与C中的sizeof(size_t)对齐?

没有

您在引用的段落中误解了size_t的使用。类型的对齐是类型的值 size_t。例如,类型char的对齐方式为(size_t)1,而仅包含单个char成员的结构本身可能具有(size_t)1的对齐方式。 (或者它可能有更大的对齐方式。)

size_t只是用于表示对齐值的类型。类型size_t的大小或对齐与结构的大小或对齐无关 - 除非结构恰好具有size_t类型的成员。

答案 4 :(得分:-3)

struct所需的对齐方式是通过其任何成员的最大对齐来衡量的。

即,只有struct类型的char将在char路线上对齐(大部分为单字节)。

包含int(有时bool使用int实现)的结构将在int对齐上对齐,并包含任何必需的填充要对齐的结构中的int

此对齐方案背后的逻辑是struct数组。

即:

/* assuming int requires a 4 byte boundary alignment */
struct example_s {
  char bytes[2];
  /* char padding[2]; //  2 byte padding so `int` is aligned */
  int i;
};

struct example_s example_array[10];

这将保证example_array[2].i正确对齐。