Search code examples
cstructmemory-alignment

Can compiler avoid padding in struct by placing them in non align address?


Let say we have the struct

struct {
    char c;
    uint32_t i;
} my_struct_t;

from what I see in the web, compilers are padding 3 bytes between the character to the uint32 for alignment. Can theoretically compiler not pad, but always put the struct in memory address 3mod(4) ?


Solution

  • This will not work because it will not work with other features of C, notably arrays and dynamic memory allocation.

    Suppose uint32_t had an alignment requirement of four bytes and the compiler used no padding in struct { char c; uint32_t i; } my_struct_t; and also required it to start at an address that were 3 modulo 4.

    Consider what happens when the programmer declares an array of my_struct_t, as in my_struct_t x[5];. The x[0] starts at an address that is 3 modulo 4, and it is 5 bytes long, so x[1] starts at an address that is 3+5 = 8 modulo 4, which is congruent to 0 modulo 4. Then the member x[1].i is at an address that is 1 modulo 4, so it is misaligned.

    Also consider what happens when the programmer dynamically allocates memory for such a structure, as in my_struct_t *p = malloc(sizeof *p);. The malloc routine is only told how many bytes to allocate. It does not know what they are for. The way this works in current C implementations is that malloc always returns memory that is aligned for any ordinary object type (the types listed in C 2018 6.2.8 2). For example, if double has an alignment requirement of eight bytes and it is the strictest alignment requirement of any of the ordinary object types, then a malloc for that C implementation always returns an address that is a multiple of eight bytes. Since this address is a multiple of eight bytes, it is also a multiple of four bytes and of two bytes and of one byte, so it works for any alignment requirement of ordinary objects. (Some malloc routines are designed to return even more strictly aligned memory, for reasons outside the scope of this answer, such as memory that is always a multiple of 16 bytes when the strictest ordinary object alignment requirement is only eight bytes.)

    You could change the C language to allow types that can never be in arrays and that could never be dynamically allocated, or you could introduce a new version of malloc that was told what alignment to provide, but these changes would complicate the language and have not been found to be useful.