Byte Count for a Struct not representing correct amount.
I am writing a bitmap loader and the byte count is not working correctly. I am currently using Xcode running a 64 bit unix executable.
The code:
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef struct {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WOR开发者_运维问答D bfReserved2;
DWORD bfOffbits;
} BITMAPFILEHEADER;
The sizeof function says the BITMAPFILEHEADER struct is 16 Bytes when it should be 14 Bytes. Any suggestions?
Your conception that it "should be 14" is mistaken. Structs are usually padded to the members' alignment. To achieve efficient packing with correct alignment, you should order the members by size.
Here's how your struct probably ends up in memory:
WORD [2]
*padding* [2]
DWORD [4] -- align to 4
WORD [2]
WORD [2] -- OK, align to 2
DWORD [4]
Even if you rearranged this to 4, 4, 2, 2, 2
, you might still end up with 16 rather than 14 since the struct may get padded to a multiple of the largest member's size.
This might be because of structure alignment. Here take a look http://peeterjoot.wordpress.com/2009/11/11/c-structure-alignment-padding/
You can force the compiler not to align the structure by adding the attribute __attribute__((__packed__))
but as far as I know it only works in gcc.
Here:
struct BITMAPFILEHEADER_S{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffbits;
} __attribute__((__packed__));
typedef BITMAPFILEHEADER_S BITMAPFILEHEADER;
The size of the struct is padded to accomodate alignment. This is, however, system dependent.
It's probably related to alignment.
Additional "padding" bytes are often added between structure/class members to ensure that each member aligns on a particular byte boundary. The result of this is that the size of the struct
can be greater than the sum of the size of it's members.
There are often (non-standard!) compiler extensions that allow you to control the way that struct's
are padded, but fiddling with the padding is often a space vs time efficiency consideration - selecting a smaller padding multiple might save you some space, but at the cost of less efficient member access...
Hope this helps.
By default there's no guarantee how any given compiler is going to align/pack the fields of a struct. There's typically a way to force it, though, for occasions just such as yours.
#pragma pack(n)
simply sets the new alignment. Reset to the default with
#pragma pack()
In your case you should use
#pragma pack(1)
A lot of machines pad structs on DWORD boundries. Normally there is a compiler option to allow you to "pack" the structs so that they are byte aligned. The other two bytes are pad bytes. This might be what you are seeing.
By default, structure members may be aligned to 4 byte boundaries for better performance. Consider using #pragma pack
if you really want the structure to be 14 bytes (but there may be a performance penalty to this).
Re-ordering the members of the structure might result in better packing.
In your particular case it looks like you are using this struct to read a BMP file - you will probably need to use #pragma pack(push,1)
before your struct and #pragma pack(pop)
afterwards to get the correct packed alignment.
See also problem writing bitmap file header in C.
In Xcode4.2 this works for me
#pragma pack(1)
struct MyStruct {
uint32_t width;
uint32_t height;
uint8_t compression;
uint8_t interlace;
};
#pragma pack()
精彩评论