结构的字节数不表示正确的数量。

时间:2011-08-22 23:53:15

标签: c++ c

我正在编写一个位图加载器,字节数无法正常工作。我目前正在使用运行64位unix可执行文件的Xcode。

代码:

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;

typedef struct {
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffbits;
} BITMAPFILEHEADER;

sizeof函数表示BITMAPFILEHEADER结构是16字节,应该是14字节。有什么建议吗?

8 个答案:

答案 0 :(得分:5)

你认为它“应该是14”是错误的。结构通常填充到成员的对齐位置。为了实现正确对齐的有效打包,您应该按尺寸订购成员。

以下是你的结构可能最终在内存中的结果:

WORD      [2]
*padding* [2]
DWORD     [4] -- align to 4
WORD      [2]
WORD      [2] -- OK, align to 2
DWORD     [4]

即使你将其重新排列为4, 4, 2, 2, 2,你仍然可能最终得到16而不是14,因为结构可能被填充到最大成员大小的倍数。

答案 1 :(得分:4)

这可能是因为结构对齐。这里看看http://peeterjoot.wordpress.com/2009/11/11/c-structure-alignment-padding/

您可以强制编译器不要通过添加属性__attribute__((__packed__))来对齐结构,但据我所知它只适用于gcc。

下面:

struct BITMAPFILEHEADER_S{
  WORD bfType;
  DWORD bfSize;
  WORD bfReserved1;
  WORD bfReserved2;
  DWORD bfOffbits;
} __attribute__((__packed__));

typedef BITMAPFILEHEADER_S BITMAPFILEHEADER;

答案 2 :(得分:1)

填充结构的大小以适应对齐。但是,这取决于系统。

答案 3 :(得分:1)

这可能与对齐有关。

通常在结构/类成员之间添加额外的“填充”字节,以确保每个成员在特定字节边界上对齐。结果是struct的大小可能大于其成员大小的总和。

通常(非标准的!)编译器扩展允许您控制填充struct's的方式,但是填充填充通常是空间与时间效率的考虑 - 选择较小的填充倍数可能为您节省一些空间,但代价是成员访问效率较低......

希望这有帮助。

答案 4 :(得分:1)

默认情况下,无法保证任何给定的编译器如何对齐/打包结构的字段。但是,对于像你这样的场合,通常有一种强迫它的方法。

#pragma pack(n)

只需设置新的对齐方式。使用

重置为默认值
#pragma pack()

在您的情况下,您应该使用

#pragma pack(1)

答案 5 :(得分:0)

许多机器在DWORD边界上填充结构。通常有一个编译器选项允许您“打包”结构,以便它们是字节对齐的。另外两个字节是填充字节。这可能就是你所看到的。

答案 6 :(得分:0)

默认情况下,结构成员可以与4字节边界对齐,以获得更好的性能。如果您真的希望结构为14个字节(但可能会对此造成性能损失),请考虑使用#pragma pack

重新订购结构的成员可能会带来更好的包装。

在您的特定情况下,您似乎使用此结构来读取BMP文件 - 您可能需要在结构之前使用#pragma pack(push,1),然后使用#pragma pack(pop)以获得正确的打包对齐。< / p>

另见problem writing bitmap file header in C

答案 7 :(得分:0)

在Xcode4.2中,这对我有用

#pragma pack(1)
    struct MyStruct {
        uint32_t width;
        uint32_t height;
        uint8_t compression;
        uint8_t interlace;
    };
#pragma pack()