sdevikar
sdevikar

Reputation: 437

How does padding work in a C compiler

I am trying to understand how padding works in a 32 bit compiler. I have boiled it down to the following sample code:

#include <stdio.h>

#define uchar unsigned char
#define ushort unsigned short

typedef struct  {                               
    ushort  a;
    ushort  b[60];
} INNER;

typedef struct{
    uchar z;
    INNER x;

}OUTER;

int main(void) {

    printf("%d\n",sizeof(INNER));
    printf("%d",sizeof(OUTER));
    return 0;
}

And the output of this program is:

122 /*actual*/
124 /*actual*/

My expectation however is

124 /*expectation*/
126 /*expectation */

Now, as far as I understand, if there was any padding that was necessary, it should have been in the INNER structure. i.e. INNER structure should have been padded as follows:

typedef struct  {                               
    ushort  a;
    ushort  b[60];
    ushort compiler_pad; /* I believe compiler should have done this */
} 

But instead, I think compiler is doing the following:

typedef struct{
    uchar z;
    INNER x;
    uchar compiler_pad; /* I believe compiler is doing this */
}OUTER;

Does anyone know why the parent structure is being padded, instead of correcting the alignment of inner structure?

Additional details: - sizeof(uchar) is 1 - sizeof(ushort) is 2 - I am on a 32 bit processor and alignment is 4 - I have already checked this question

Upvotes: 1

Views: 226

Answers (1)

zwol
zwol

Reputation: 140445

INNER is 61 ushort scalars in a row, which fits exactly into 122 bytes; when allocated by itself, it doesn't require any padding. That is why there is no padding inside an INNER.

OUTER, however, consists of one uchar (whose size is 1 by definition) and then 61 ushorts. The hardware alignment requirement for ushort is 2, not 1, so the compiler must insert one byte of padding between the uchar and the 61 ushorts, i.e. before the INNER object, so that their alignment requirement is satisfied. Padding at the end of the INNER as you expected would not arrange for INNER to be properly aligned within OUTER.

EDIT: The compiler is inserting padding in between z and x, not at the end of OUTER:

typedef struct {
    uchar z;
    uchar compiler_pad;
    INNER x;
} OUTER;

You can confirm this for yourself by adding #include <stddef.h> at the top of your program and then printing offsetof(OUTER, x). The number printed will be 2.

Upvotes: 3

Related Questions