The line with *ap =
is a strict aliasing violation: an object of type B
is written using an lvalue expression of type A
.
Supposing that line was not present, and we moved onto ap->x = 10; ap->y = 20;
. In this case an lvalue of type int
is used to write objects of type int
.
There is disagreement about whether this is a strict aliasing violation or not. I think that the letter of the Standard says that it is not, but others (including gcc and clang developers) consider ap->x
as implying that *ap
was accessed. Most agree that the standard's definition of strict aliasing is too vague and needs improvement.
Sample code using your struct definitions:
void f(A* ap, B* bp)
{
ap->x = 213;
++bp->x;
ap->x = 213;
++bp->x;
}
int main()
{
B b = { 0 };
f( (A *)&b, &b );
printf("%d
", b.x);
}
For me this outputs 214
at -O2
, and 2
at -O3
, with gcc.
The generated assembly on godbolt for gcc 6.3 was:
f:
movl (%rsi), %eax
movl $213, (%rdi)
addl $2, %eax
movl %eax, (%rsi)
ret
which shows that the compiler has rearranged the function to:
int temp = bp->x + 2;
ap->x = 213;
bp->x = temp;
and therefore the compiler must be considering that ap->x
may not alias bp->x
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…