Search code examples
clanguage-lawyerundefined-behaviorunionsmemory-alignment

Is accessing a member of an unaligned union undefined behavior even if the member being accessed is sufficiently aligned?


In C bad things can happen if I try to access a type through a pointer that is not aligned:

int x[2]; // Assuming CHAR_BIT == 8 && sizeof(int) == 4
*(int *)((char *)x+1) = 10; /* Undefined behavior due to unaligned pointer dereference
    even though there are no out of bounds accesses */

However what if the type in question is a union but I am only accessing a member of the union that does not have the alignment requirements?

union X {
    int i;
    char c[4];
} x[2];
((union X *)((char *)x+1))->i = 10; /* I am guessing this is still undefined behavior
    because accessing an unaligned int through a union does not make a difference as far as I know */

But would the following invoke undefined behavior?

((union X *)((char *)x+1))->c[0] = 10;

I am in doubt because on one hand I am dereferencing a union pointer via the -> operator and the union has alignment requirements because of the int field, but on the other hand, I am not touching the int field. So does that result in any unaligned pointer access violations?


Solution

  • The cast causes undefined behavior. From C23 6.3.2.3(7)

    A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.

    Since (union X *)((char *)x+1)) is not correctly aligned for the union, the second sentence applies. It doesn't matter whether you actually dereference it.