【问题标题】:C++ The compiler is changing the alignment of my structures. How can I prevent this?C++ 编译器正在改变我的结构的对齐方式。我怎样才能防止这种情况?
【发布时间】:2017-06-19 00:23:14
【问题描述】:

我正在编写一些代码来读取位图文件。

这是我用来读取位图标题的结构。另见:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx

struct BITMAPFILEHEADER
{
        WORD  bfType; // 2
        DWORD bfSize; // 6
        WORD  bfReserved1; // 8
        WORD  bfReserved2; // 10
        DWORD bfOffBits; // 14
}; // should add to 14 bytes

如果我将以下代码放在我的主函数中:

std::cout << "BITMAPFILEHEADER: " << sizeof(BITMAPFILEHEADER) << std::endl;

程序打印:

BITMAPFILEHEADER: 16

它似乎在 4 字节边界上重新对齐结构中的数据,大概是为了提高效率。当然,这使我无法读取位图...即使 microsoft 和其他人,请指定这是执行此操作的方法...

如何防止结构重新对齐?

【问题讨论】:

  • 为什么这会导致它无法使用?您确实意识到应该将数据反序列化到您的程序中?
  • 因为当我读取 sizeof(BITMAPFILEHEADER) 时,读取的不是 14 个字节,而是 16 个字节。
  • 您是在自己创建这个结构定义吗? windows.h 标头已经包含了这个和pragma 的必要集以使大小为 14。
  • 这很烦人,但你不能只读取 14 个字节吗?
  • 不幸的是,有些字节没有对齐

标签: c++ bitmap c++14 file-format


【解决方案1】:

我找到的适用于 gcc 编译器的解决方案,在 linux 下:

struct BITMAPFILEHEADER
{
        WORD  bfType;
        DWORD bfSize;
        WORD  bfReserved1;
        WORD  bfReserved2;
        DWORD bfOffBits;
} __attribute__((packed));

可能有更好、更跨编译器/平台的处理方式,但我不知道它是什么。

【讨论】:

【解决方案2】:

为避免这种情况,您显然可以指定编译粒度。只需使用此开关:

##pragma pack(1)

这告诉编译器对齐 1 字节边界(什么都不做)

恢复正常填充(从之前的#pragma pack):

#pragma pack(pop)

【讨论】:

  • 这是否适用于全局,所以所有代码都在编译?
  • 是的,它是一个全局开关
  • 我想这使得在同一个代码中不可能同时拥有这两个功能......自动对齐和打包以使用 IO
  • @user3728501 可以在编译代码中使用push和pop pragmas打开和关闭开关。
  • @user3728501 -- 这就是 Windows.h 标头的工作方式。 windows.h 中使用了特殊的#include 文件,即pshpack2.h 和poppack.h,它们围绕着应该以某种方式对齐的结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多