Why padding are added, if char comes after int?

2019-01-12 04:19发布

问题:

For example, there is a structure

struct A
{
char a;
int i;
};

In this case, we have a[1 byte] + padding[3 byte] + int[4 byte] = 8.

Now let's make little update into struct above,

struct A
{
int i;
char a;
};

In this case char comes after int and no need to add padding bytes, it means sizeof(A) = 5 byte, but in this case I also get the 8 byte result. Why ?

Ok, and what about this case

struct s
   {
       int b;
       double c;
       char a;
   };

According logic given below, there is a: size = b[4 bytes] + padding[4 bytes] + c[8] + a[1] + padding[7 bytes to align with double] = 24, but after execution I get 16. How this is possible ?

回答1:

In this case char comes after int and no need to add padding bytes, it means sizeof(A) = 5 byte, but in this case I also get the 8 byte result. Why ?

First you need to understand why padding is needed?
Wiki says that:

Data structure alignment is the way data is arranged and accessed in computer memory. It consists of two separate but related issues: data alignment and data structure padding. When a modern computer reads from or writes to a memory address, it will do this in word sized chunks (e.g. 4 byte chunks on a 32-bit system) or larger. Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

To make the size multiple of 4 (alignment of int) , the second snippet will be padded with 3 bytes. After compilation the second snippet will be padded for proper alignment as

struct A
{
    int i;
    char a; 
    char Padding[3]; // 3 bytes to make total size of the structure 8 bytes
};    

EDIT: Always remember the two golden rules of structure padding:

  • Padding is only inserted when a structure member is followed by a member with a larger alignment requirement or at the end of the structure.
  • The last member is padded with the number of bytes required so that the total size of the structure should be a multiple of the largest alignment of any structure member.

In case of

struct s
{
    int b;
    double c;
    char a;
};  

alignment will take place as

struct s
{
    int b;             // 4 bytes. b is followed by a member with larger alignment.
    char Padding1[4];  // 4 bytes of padding is needed 
    double c;          // 8 bytes
    char d;            // 1 byte. Last member of struct. 
    char Padding2[7];  // 7 bytes to make total size of the structure 24 bytes 
};   

Also note that by changing the ordering of members in a structure, it is possible to change the amount of padding required to maintain alignment. This can be done by if members are sorted by descending alignment requirements.

struct s
{ 
    double c;   // 8 bytes
    int b;      // 4 bytes 
    char a;     // 1 byte. Only last member will be padded to give structure of size 16 
};   


回答2:

The reason the compiler have to add padding at the end of your struct is that the struct can be part of an array, and each element of an array must be properly aligned.

It seems your platform wants an int to be aligned to 4 bytes.

If you declare an array of your struct A:

struct A array[2];

Then the first int member of array[1] should also have an alignment of 4 bytes. So the compiler pads your struct A to be 8 bytes to accomplish that, whilst if it didn't add any padding and sizeof(struct A) were 5 bytes, array[1] would not be properly aligned.

(Keep in mind that a compiler can't insert padding inbetween array elements, padding have to be part of the array elements themselves since sizeof array must be the same as sizeof(struct A) * 2 in the above case)



回答3:

Not only each member of the struct has to be data aligned, but the struct itself has to aligned to the size of the largest member in the struct. So, padding is added to struct A such that its size should be a multiple of the larger of sizeof i and sizeof a.

Have a look at C FAQ here



回答4:

If one is going to have an array of structures, all elements within the array must have the same size and alignment; this would imply that for things in an array the size must be a multiple of alignment. The only time it would be useful to have a structure whose size was not a multiple of alignment would be if it was not incorporated directly into another array, but was instead used as part of another structure. That kind of situation does occur sometimes, but not sufficiently often as to merit special attention in the language design.