强制结构大小为8个字节

时间:2015-05-13 11:17:08

标签: c++ c struct

我的结构应该是8字节大小。

struct Slot {
    uint8_t T;
    uint8_t S;
    uint32_t O : 24;
    uint32_t L : 24;
}

然而,sizeof(Slot)告诉我大小是12字节。 所以编译器似乎填充数据虽然它不应该是必要的(可能是因为24位无法正确对齐)。

一个hacky解决方案是使用3个单字节字段而不是单个3字节字段:

struct Slot2 {
    uint8_t T;
    uint8_t S;
    uint8_t O1;
    uint8_t O2;
    uint8_t O3;
    uint8_t L1;
    uint8_t L2;
    uint8_t L3;
}; // sizeof(Slot2) = 8

还有其他方法可以达到这个目的吗?

7 个答案:

答案 0 :(得分:3)

这在MSVC上给出了大小为8个字节而没有打包编译指示。

struct Slot {
    uint32_t O : 24;
    uint32_t T : 8;
    uint32_t L : 24;
    uint32_t S : 8;
};

答案 1 :(得分:3)

由于C标准很难指定位字段的行为,因此任何人都无法判断您的代码将执行什么操作或数据将如何在内存中结束。 See this

  • 未指定将uint32_t用于位字段时会发生什么。
  • 你不知道是否会有填充位。
  • 你不知道是否会有填充字节。
  • 您无法知道填充位或字节的最终位置。
  • 您无法知道第二个24位块的8位是否在前一个数据之后立即结束,或者它是否与下一个32位段对齐。
  • 你不知道哪个是msb,哪个是lsb。
  • Endianess会导致问题。

解决方案是根本不使用位字段。请改用按位运算符。

答案 2 :(得分:2)

你的" hack"解决方案是正确的。我怀疑布局是由一些外部因素决定的,因此您无法以更好的方式将其映射到结构。我怀疑24位数字中的字节顺序也是由外部决定的,而不是由编译器决定的。

要处理这种情况,字节结构或只是字节数组是最简单和可移植的解决方案。

答案 3 :(得分:0)

我认为,你想要的是8字节,不是C标准可以保证的,用你的第一个定义。

相关:来自C11标准,章节§6.7.2.1,

  

实现可以分配足够大的任何可寻址存储单元来保存位域。如果剩余足够的空间,则紧跟在结构中的另一个位字段之后的位字段将被打包到相同单元的相邻位中。 如果剩余空间不足,是否将不适合的位字段放入下一个单元或重叠相邻单元是实现定义的。

但是,如果你可以调整变量以便它们能够以32位对齐方式正确地拟合,那么你可以找到出路,那么

24 + 8 + 24 + 8 = 64位= 8字节。

您可以使用大小为8字节的结构。

答案 4 :(得分:0)

使用此编译器相关解决方案(与gcc,msvc一起使用),结构将为8个字节:

#pragma pack(push, 1)
struct Slot {
    uint8_t T;
    uint8_t S;
    uint32_t O : 24;
    uint32_t L : 24;
};
#pragma pack(pop)

这会将结构的对齐方式设置为1个字节。

答案 5 :(得分:0)

在MSVC上,以下方法可以使您的变量订单保持不变:

struct Slot {
    uint64_t T : 8;
    uint64_t S : 8;
    uint64_t O : 24;
    uint64_t L : 24;
};

虽然编译器不能保证这一点。 YMMV在其他编译器上。

答案 6 :(得分:-3)

尝试如下所示的内容:

struct Slot {
    uint32_t O : 24;
    uint8_t T;
    uint32_t L : 24;
    uint8_t S;
};