Search code examples
calignmentstructuresizeof

Why the size of this structure is same irrespective of the order of the members?


As memory alignment of the structure in C is done in a contiguous form for the first element first and then second, then third and so on... along with bit padding, then why the size of this structure is same even when the elements are rearranged:

#include <stdio.h>

int main(void)
{
    struct student
    {
        float c;
        int a;
        char b;
    };
    printf("%zu\n", sizeof(struct student));
    return 0;
}

Output: 12

Does the memory alignment looks like this for the above configuration of structure?:

f f f f i i i i c
_ _ _ _ _ _ _ _ _ _ _
0 1 2 3 4 5 6 7 8 9 10

Solution

  • It appears that on your machine both int and float require 4 bytes each. In this sense, their location in the struct is irrelevant.

    However, a char takes (usually) only 1 byte, so you might wonder how come sizeof doesn't return 9 (4+4+1) and the reason is padding.

    Padding is added in a number of situations, but most obviously to allow for type alignment (I assume that both the int and float types on your system are naturally aligned on the 4 byte boundary).

    I assume that this would make perfect sense if the order was changed to:

    struct student
    {
        float c;
        char b;
        int a;
    };
    

    In this example we would have 4 bytes (float) + 1 byte (char) + 3 bytes (padding) + 4 bytes (int). i.e.:

    struct student
    {
        float c;
        char b;
        char padding[3];
        int a;
    };
    

    However, in your original example we have:

    struct student
    {
        float c;
        int a;
        char b;
    };
    

    This results in 4 bytes (float) + 4 bytes (int) + 1 byte (char) + 3 bytes (padding) - i.e.:

    struct student
    {
        float c;
        int a;
        char b;
        char padding[3];
    };
    

    The reason we still get padding at the end of the struct is to allow for Arrays (struct student array[32]).

    If there wasn't any padding at the end of the struct than the second member of the array (array[1]) would start on an offset and the type (float) wouldn't be properly aligned on the natural 4 byte boundary.

    When you declare the type, the compiler will always add the required padding that allows the type to be used in an array (i.e., when allocating memory using malloc).

    I hope this answers your question.


    EDIT:

    To clarify the padding in the remaining struct that I hadn't listed above (see comment), it would probably look something like this (assuming the compiler is compiling code for a similar system):

    struct student
    {
        char b;
        char padding[3];
        float c;
        int a;
    };
    

    If a was a char as well, we would get padding in both ends of the struct:

    struct student
    {
        char b;
        char padding[3];
        float c;
        char a;
        char padding2[3];
    };
    

    However, if we re-organized the struct so the chars were next to each other, their padding would be different since the char type doesn't have a natural alignment of 4 bytes on this system:

    struct student
    {
        char b;
        char a;
        char padding[2];
        float c;
    };
    

    Note:

    Most compilers should support an instruction that tells the compiler to "pack" the structure (ignore type alignment and padding)... this, however, should be highly discouraged IMHO since it could cause some CPU architectures to crash and introduces non-portable code (see also here).