Why favour data structure alignment?

2019-04-08 19:12发布

问题:

The type of each member of the structure usually has a default alignment i.e.each structure member is aligned on a pre-determined boundary. For this reason the padding is performed in the following wiki example:

struct MixedData
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;
};



struct MixedData  /* After compilation in 32-bit x86 machine */
{
    char Data1; /* 1 byte */
    /* 1 byte for the following 'short' to be aligned on a 2 byte boundary 
assuming that the address where structure begins is an even number */
    char Padding1[1];
    short Data2; /* 2 bytes */
    int Data3;  /* 4 bytes - largest structure member */
    char Data4; /* 1 byte */
    char Padding2[3]; /* 3 bytes to make total size of the structure 12 bytes */
};

What is the (practical) reason that alignment should be preserved?

回答1:

Unaligned reads and writes usually require the CPU to fetch the two adjacent words from memory (instead of just one) and to apply some additional bitwise arithmetic in order to perform the designated operation properly.

Some architectures, like x86 will allow it at a performance cost. Other architectures (most notably ARM), will either raise an exception (usually resulting in a SIGBUS signal for a user process) or even "round" the address to the closest boundary which could result in some very nasty bugs.



回答2:

On many architectures, aligned reads and writes from and to main memory are much faster than their unaligned counterparts.



回答3:

Usually, structure are aligned on a processor dependent alignment to make accessing them as quick as possible using the processors 'natural' register size.

For 32-bit processors, it's 4 bytes (or 32-bits), for 64-bit processors it's 8 bytes.

Some (non x86) processors will generate a fault if you try to access (say) an int if it's not aligned on the correct boundary.

Communication between different devices is a practical reason to preserve alignment. With default alignment, this structure would be 24 bytes long, whereas on a 64-bit processor, it would be 48 bytes, and non of the items except the first would be in the same place.

It is normally possible to change the structure padding with a compiler/pragma directive which may negate the need for the manual padding specified in your example, but that's typically different for each compiler.