The size of a class can be changed simply by altering the order of its member declarations. Most processors require specific memory alignment on variables of certain types
Alignment rules
bool
variables can be byte aligned and appear at any byte boundary.short
(2 byte) variables must be 2 byte aligned, they can appear at any even byte boundary. This means that 0x1005 is not a valid location for a short variable, but 0x1006 is.int
(4 byte) variables must be 4 byte aligned, they can only appear at byte boundaries that are a multiple of 4 bytes. This means that 0x1006 is not a valid location for along
variable, but 0x1008 is.
So, structure padding occurs because the members of a structure must appear at the correct byte boundary. To achieve this, the compiler puts in padding so that the structure members appear in the correct location. And the size of the structure should be aligned to the memory so that the padding will occur at the end of the structure too.
struct INF
{
bool binfFlag1;
unsigned short usNumber;
bool binfFlag2;
int nNumber;
bool binfFlag3;
};
In this example, the alignment is as follows:
binfFlag1
(bool
) can appear at any byte boundary (as per rule 1). So, imagine that the memory allocation for the structureINF
starts at location 0x1004 and the first memberbinfFlag1
takes up that location for its 1 byte size storage.usNumber
(short
) should have its first byte appearing at an even location. So it can not take up the location 0x1005. It will take the locations 0x1006 and 0x1007. The location 0x1005 is padded (as per rule 2).binfFlag2
(bool
) can then appear in the next available memory location. So it occupies 0x1008 (as per rule 1).nNumber
(int
) must start at a location which is the multiple of 4. The next possible location fornNumber
is 0x100C. So, there are 3 padding bytes betweenbool
andint
(as per rule 3).bStatus
(bool
) then appears in the available memory location; however, because the structure contains anint
member, the structure must be 4 byte aligned and must be a multiple of 4 bytes in size. Therefore, there are 3 padding bytes at the end of the structure.
The structure would be 16 bytes long.
For optimization, the structure can be re-written like this:
struct INF
{
int nNumber;
unsigned short usNumber;
bool binfFlag1;
bool binfFlag2;
bool binfFlag3;
};
The
int
appears at the correct byte alignment. The short
will be correctly aligned, so no need for padding between the int
and short
. The three bool
s can appear at any location. The structure must be a multiple of 4 bytes in size since it contains an int
, so 3 padding bytes appear after the last bool
. Now, it is only 12 bytes long. So we saved 4 bytes by proper alignment of variables.How to avoid structure padding using pragma?
The default compiler alignment is of 4 bytes. We need to change it to 1 byte.
For that, do the following steps:
- Push the current compiler alignment into the stack.
- Set the alignment into 1 byte.
- Declare the structure.
- Restore the default compiler alignment from the stack.
Example:
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
struct MyPackedData
{
char Data1;
long Data2;
char Data3;
};
#pragma pack(pop) /* restore original alignment from stack */
Thus the structure size is 6 bytes.
See Also
C++ topics
No comments:
Post a Comment