【问题标题】:How to pack a struct tightly on Windows?如何在 Windows 上紧密打包结构?
【发布时间】:2019-10-30 09:28:18
【问题描述】:

我正在尝试创建一个打包结构,它代表特定数据包的标头。因此,它不能有任何填充以匹配规范中给出的大小。但是,在 Windows 上,无论我如何告诉编译器紧密打包结构,它都会在最后一个字段之后有一个 1 字节的填充。

我已经在 Compiler Explorer 上尝试过这段代码,并且在大多数平台上都得到了我想要的结果,除了 MSVC。我还尝试了带有 GCC 的 Windows Subsystem for Linux (WSL),这再次给了我正确的结果。我只在 Windows 上遇到了填充问题。

结构的简化版如下所示:

typedef struct
{
    unsigned a : 10;
    unsigned b : 1;
    unsigned c : 5;
    unsigned d : 8;
} __attribute__((packed)) A;

使用 MSVC:

#pragma pack(push, 1)
typedef struct
{
    unsigned a : 10;
    unsigned b : 1;
    unsigned c : 5;
    unsigned d : 8;
} A;
#pragma pack(pop)

在 MSVC 的情况下,我还尝试将 /Zp1 编译器参数添加为默认为 1 字节对齐。

我希望结构的大小为 3 字节。在带有 gcc 或 clang 的 Linux 上没问题,但在带有 MinGW GCC 或 MSVC 的 Windows 上,大小始终为 4 字节。

【问题讨论】:

  • unsigned int /* assumes 24+ bits */ A; unsigned a = A & 0x3ff; unsigned b = (A && 0x400) >> 10; ...

标签: c++ c windows struct padding


【解决方案1】:

如果你把类型改成这样:

#pragma pack(push, 1)
typedef struct
{
    unsigned short a : 10;
    unsigned short b : 1;
    unsigned short c : 5;
    unsigned char d : 8;
} A;
#pragma pack(pop)

然后它确实以 3 个字节出现。

您也可以手动模拟位域,以尽量减少此类意外。

【讨论】:

  • 我认为它可以工作,因为前 3 个字段适合 16 位,最后一个适合 8 位,并且由于它不为所有字段使用 4 字节无符号类型,因此无需在最后一个字段之后添加额外的字节。我说的对吗?
猜你喜欢
  • 2014-02-01
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 2011-10-07
相关资源
最近更新 更多