Standard C states that smoothing across unions is explicitly permitted.
However, check the following code:
void func(int *a, short *b) { *a = 1; printf("%f\n", *b); }
The goal of the strict anti-aliasing rule is that a and b should not be considered a pseudonym. However, you can call func(&u.f1, &u.f2); .
To solve this problem, common sense is to say that the “workaround resolution” that unions should avoid using a strict pseudonym rule applies only when union members are addressed by name.
The standard does not explicitly state this. It can be argued that “if a member used ...” (6.5.2.3) actually indicates that a “bypass” occurs only when accessing a member by name, but it is not 100% clear.
However, it is difficult to find an alternative and self-consistent interpretation. One possible alternative interpretation is along the lines in which the notation func(&u.f1, &u.f2) calls UB, because the overlapping objects are passed to a function that "knows" that it does not receive overlapping objects - kind of like breaking a restrict .
If we apply this first interpretation to your example, we would say that *a in your printf calls UB because the current object stored in this place is short , and 6.5.2.3 does not hit because we do not use a union member by name.
I would suggest, based on your published results, that gcc uses the same interpretation.
This has been discussed here, but I cannot find this thread right now.
source share