https://kukuruku.co/post/i-do-not-know-c/
Problem #7:
#include <stdio.h>
void f(int *i, long *l)
{
printf("1. v=%ld\n", *l); /* (1) */
*i = 11; /* (2) */
printf("2. v=%ld\n", *l); /* (3) */
}
int main()
{
long a = 10;
f((int *) &a, &a);
printf("3. v=%ld\n", a);
return 0;
}
Output on two different compilers on a little endian system is:
1. v=10 2. v=11 3. v=11
1. v=10 2. v=10 3. v=11
How is the second result possible ? I didn't quite get how the explanation that explains the result by referring to strict aliasing. Does the compiler ignore the line (2) totally ?
Quoting Wikipedia:
In C or C++, as mandated by the strict aliasing rule, pointer arguments in a function are assumed to not alias if they point to fundamentally different types, except for char* and void*, which may alias to any other type. Some compilers allow the strict aliasing rule to be turned off, so that any pointer argument may alias any other pointer arguments. In this case, the compiler must assume that any accesses through these pointers can alias. This can prevent some optimizations from being made.
This is where the rule is violated:
f((int *) &a, &a);
^ aliasing to different type (a is 'long')
^ passing the same variable with different type
The problem is that assuming strict aliasing rules, first and second argument of the function point to another location because these are of different types. That is why author explains:
Therefore, we can assume that any long has not changed.
And in here: printf("2. v=%ld\n", *l); a long value is dereferenced.
That is why this part (2) is undefined behaviour on both compilers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With