Strict aliasing refers to when a pointer is converted to another pointer type, after which the contents are accessed. Strict aliasing means that the involved pointed-at types must be compatible. That does not apply here.
There is however the term pointer aliasing, meaning that two pointers can refer to the same memory. The compiler is not allowed to assume that this is the case here. If it wants to do optimizations like those you describe, it would perhaps have to add machine code that compares the pointers with each other, to determine if they are the same or not. Which in itself would make the function slightly slower.
To help the compiler optimize such code, you can declare the pointers as restrict
, which tells the compiler that the programmer guarantees that the pointers are not pointing at the same memory.
Your function compiled with gcc -O3
results in this machine code:
0x00402D09 mov $0x1,%edx
Which basically means that the whole function was replaced (inlined) with "set a.x to 1".
But if I rewrite your function as
int test_func(A* restrict a, int* restrict x)
{
a->x = 0;
*x = 1;
return a->x;
}
and compile with gcc -O3
, it does return 0. Because I have now told the compiler that a->X
and x
do not point at the same memory, so it can assume that *x = 1;
does not affect the result and skip the line *x = 1;
or sequence it before the line a->x = 0;
.
The optimized machine code of the restrict version actually skips the whole function call, since it knows that the value is already 0 as per your initialization.
This is of course a bug, but the programmer is to blame for it, for careless use of restrict
.