I have a struct A that contains a struct B and I access A via a pointer pa and b via pointer ba. Is this undefined behavior (Strict Aliasing Rule)? (The struct B part is not accessed by the pointer to struct A pa.)
Note that there is no cast but still there are pointers of different types referring to the same memory.
struct B {int x;};
struct A { int foo; struct B b; int bar;};
struct A global_a = { 1, { 2 }, 3 };
struct A * get_ptr_to_struct_A()
{
return &global_a;
}
void modify_struct_B(struct B * p)
{
p->x++;
}
int main()
{
struct A local_A;
struct A * pa = get_ptr_to_struct_A();
struct B * pb = &pa->b;
local_A = *pa; // First assignment
modify_struct_B(pb);
local_A = *pa; // 2nd assignment. Can the compiler chose to skip this?
}
According to the strict aliasing rule, the compiler can assume that pointers of different types do not point to the same memory. Hence, the compiler can draw the conclusion that the second assignment is meaningless and optimize it away. (I.e. it assumes that the pointer pb points somewhere where the pointer pa does not point.)
What prevents the compiler from ignoring the second assignment?
Short answer is not undefined behavior.
Why?
papoints toglobal_awhich containsfoo=0,b.x=0, andbar=0.Now
pbpoints to (has the address of)global_a.b.You are passing a valid pointer to an instance of
struct B(pb->x=0).It just increments
pb->x, so after this,pb->x=1.Every step is deterministic and there is no room for the compiler to implement something different.
The strict aliasing rule is not at play here because you are not aliasing anything since you are not reinterpreting or casting any pointer.
In https://en.cppreference.com/w/c/language/object, it states that is about interpreting
T2reference as aT1reference.So you would have undefined behavior if:
struct A