Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the compiler adding padding to a struct that's already 4-byte aligned?

Tags:

c

gcc

This issue has been reproduced using multiple 32-bit architectures

I have the following struct in which the sum of all the data member sizes is 76 bytes:

typedef struct
{


    uint32_t unused_32;

    //Unrolled arrays
    uint8_t ar1_1;
    uint8_t ar1_2;

    uint8_t ar2_1;
    uint8_t ar2_2;

    uint8_t ar3_1;
    uint8_t ar3_2;

    uint8_t ar4_1;
    uint8_t ar4_2;
    uint8_t ar4_3;
    uint8_t ar4_4;
    uint8_t ar4_5;
    uint8_t ar4_6;


    uint8_t ex1;
    uint8_t ex2;
    uint8_t ex3;
    uint8_t ex4;
    uint8_t fsi_1;
    uint8_t fsi_2;
    uint8_t fsi_3;
    uint8_t fsi_4;


    uint64_t ex5;
    uint64_t ex6;
    uint64_t Unused_1;
    uint64_t Unused_2;
    uint64_t Unused_3;
    uint64_t Unused_4;

    uint32_t Crc;       

} testStruct;

However, when I do a sizeof() on the struct I get 80 bytes and I'm having trouble figuring out why. When I set the preprocessor to use the "#pragma pack(1)" option and do a sizeof(), it returns 76 bytes, indicating that the compiler is adding padding.

I printed out the addresses of every data member of the structure and everything is in sequential order in memory with no 'holes'. I also added an initialization for a 32-bit integer before the struct and printed out its address, and it came right before the first datamember of the struct, indicating that the padding that's being added is at the end.

76 bytes is already 4-byte aligned, why is the compiler adding an additional 4 bytes onto the end of the struct to make it 80 bytes?

like image 243
tyler124 Avatar asked Oct 26 '25 03:10

tyler124


2 Answers

From the GCC documentation:

Note that the alignment of any given struct or union type is required by the ISO C standard to be at least a perfect multiple of the lowest common multiple of the alignments of all of the members of the struct or union in question.

In other words, because your struct contains members of type uint64_t (aligned to 8 bytes), the struct itself must be aligned to an 8-byte boundary.

like image 60
Elan Hamburger Avatar answered Oct 28 '25 20:10

Elan Hamburger


As OP was able to use #pragma pack(1), an implementation specific directive, it implies that the size of the structure could be packed to 76 bytes rather than 80 on OP's platform.

With such packing, an array of testStruct would certainly cause uint64_t members to occur on non-octal addresses. By padding the structure with 4, an array of testStruct, starting on an octal address would have all uint64_t members in each element aligned for potential optimal code/speed.

This is a common trade off compilers make to optimize, code, speed and memory usage.


Most coding tasks should not assume a packed structure.

For code that needs precise layout, either implementation directive like #pragma pack(1) are needed or for portability, another non-struct approach is needed.

like image 41
chux - Reinstate Monica Avatar answered Oct 28 '25 21:10

chux - Reinstate Monica