Consider the following ISO C code:
struct S {
int a;
};
void f() {
struct S s;
*(int*)&s = 1; // 1
((struct S*)(struct Opaque*)&s)->a = 2; // 2
*(int*)(struct Opaque*)&s = 3; // 3
}
Does this code contain any undefined behavior?
My own understanding is:
- Statement 1 does not trigger undefined behavior because of C17 §6.7.2.15 “A pointer to a structure object, suitably converted, points to its initial member and vice versa”
- Statement 2 does not trigger undefined behavior, despite the casts, because we are accessing the object through its effective type
S
, therefore it does not violate the strict aliasing rule (C17 §6.5.7) - But what about statement 3?
Opaque
is not defined as having a first member of typeint
, so it seems that 6.7.2.15 does not apply (the unclear meaning of “suitably converted” tends to muddy the waters here). And the strict aliasing rule does not seem to allow accessing an object of effective typeS
through anint
pointer (though it does allow the reverse). So, is statement 3 undefined behavior or not?