我正在编写一个位图加载器,字节数无法正常工作。我目前正在使用运行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字节。有什么建议吗?
答案 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>
答案 7 :(得分:0)
在Xcode4.2中,这对我有用
#pragma pack(1)
struct MyStruct {
uint32_t width;
uint32_t height;
uint8_t compression;
uint8_t interlace;
};
#pragma pack()