Reputation: 432
In the following code:
#include <stdio.h>
int main(void)
{
int n = 74;
int * pn = &n;
short * sp;
//sp = (short *)&n; // <-- bad
sp = (short *)pn; // <-- fine
*sp = 4;
printf("%d\n", *sp);
return 0;
}
does the strict aliasing rule get broken? As far as I understand, it does, since a pointer to a short points to an int. But the compiler does not complain even if compiled with (assuming the code is in test.c)
gcc test.c -o test.exe -Wall -std=c99 -Wstrict-aliasing=2 -O3
However, it does complain if the line marked as bad is uncommented, and the one marked as fine is commented.
Can someone please explain does this case really break the rule? If so, why is it not detected by the compiler? If not, why not, since according to the standard it should?
Upvotes: 1
Views: 770
Reputation: 320787
It is not the casting per se that violates strict-aliasing, it is the subsequent invalid lvalue access (memory reinterpretation) that violates it.
Strict-aliasing violations are really run-time violations: they are defined through dynamic type of the objects accessed as lvalues. For this reason, it is not always possible to catch strict-aliasing violations at compile time.
Consider the following code snippet
short n = 0;
int *pn = (int *) &n; // 1
short *sp = (short *) pn; // 2
*sp = 4;
This code does not violate strict-aliasing rules even though it contains the same cast (2) as your original code. Even though pointer pn
is declared as int *
, at run time it actually points to an object of type short
. So, the cast to short *
and subsequent assignment to the pointee is perfectly valid. (Assuming the pointer value survives this round-trip cast.)
In cases like this the compiler apparently strives to catch the very first cast in the chain of casts: the one that that appears to be a rather obvious precursor to a potential strict-aliasing violation - cast 1 in my example. Cast 2 has fairly high potential to produce a false positive (as in my example) and the compiler does not warn about it.
Upvotes: 2
Reputation: 1506
It's hard for the compiler to catch the violation at compile time unless you assign a new value by dereferencing into a different type as shown below. If you change your code as shown below you will get the warning you were expecting.
int main(void)
{
int n = 74;
//int * pn = &n;
//short * sp;
//sp = (short *)&n; // <-- bad
//sp = (short *)pn; // <-- fine
*((short*)&n) = 4;
printf("%d\n", n);
return 0;
}
This question shows the exact same problem and provides even more details. GCC: accuracy of strict aliasing warnings
The other answer by AnT began with this statement: "It is not the casting per se that violates strict-aliasing, it is the subsequent invalid lvalue access (memory reinterpretation) that violates it." .... That is correct. My example attempts an lvalue access that violates the rule so you get the warning.
Upvotes: 2