I think your compiler uses 4-byte allignment for the fields.
The individual fields in a structure need to be aligned appropriately. The compiler will pad additional space in the structure in order to satisfy alignment requirements.
If you don't want this, you can use the UNALIGNED
macro.
It's because the 4 byte ints are aligned to a 4 byte boundry, so there are 2 bytes of padding after bfType.
Alignment. Likely on your platform ints have to be 4byte aligned and shorts are 2byte aligned.
+0 -1 : bfType
+2 -3 : <padding>
+4 -7: bfSize
+8 -9: bfReserve1
+10 -11: bfReserve2
+12 -15: bfOffBits
-------------
16 bytes
Alignment is good because unaligned structures require extra work for many architectures.
because of the way memory is allocated, there will be padding after a short
ISO C++03, 9.2[class.mem]/12:
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
This issue comes because of a concept known as alignment. In many cases, it is desirable to have a number placed at an address that is a multiple of the size of the number in bytes (up to some maximum, often the pointer size of the platform). A variable so placed is said to be aligned to a n-byte boundary, where n is the number. The exact effects of this depend on the processor. Many processors perform math faster if the data is properly aligned. Some are even incapable of performing operations (sometimes even load operations) on unsuitably-aligned data - in order to work on such data, it has to be loaded into two registers and then a series of bit shifts and masks need to be performed to get a usable value, and then it needs to be put back. Think of it like storing half of the int
in each of two buckets and needing to put them together to use it, rather than simply storing the whole int
in one bucket.
In your case, the initial bfType
likely needs to be aligned to a 2-byte boundary, while bfSize
likely needs to be aligned to a 4-byte boundary. The compiler has to accomodate this by aligning the entire struct to 4 bytes, and leaving 2 unused bytes between bfType
and bfSize
.
When compiling on the same system, however, the padding is probably going to be consistent, possibly depending on compiler options and the specific ABI used (generally, you're safe on the same platform unless you are trying to make things incompatible). You can freely make another struct with the same first 5 members, and they will take up 16 bytes of the other struct, in the exact same positions.
If you really need to avoid this behavior, you will have to check your compiler documentation. Most compilers offer an attribute or keyword to declare a variable as having no alignment, and another one to indicate that a struct should have no padding. But these are rarely necessary in the general course of things.
Just remember:
- The size of a structure may not equal the sum of the size of the fields.
- Don't use structures a data stencils. They can model the data. Problems arise otherwise.
- The data should be assigned to the
members individually; don't use
memcpy
orfread
oristream::read
.
If you feel that this is a performance issue, allocate a huge unsigned char
buffer, read data into the buffer then assign from buffer to the members of the structure. Remember that memory transfers are faster the I/O transfers.