As previously established, a union of the form
union some_union {
type_a member_a;
type_b member_b;
...
};
with n memb
The strict aliasing rule forbids access to the same object by two pointers that do not have compatible types, unless one is a pointer to a character type:
7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
In your example, *f = 1.0; is modifying fi.i, but the types are not compatible.
I think the mistake is in thinking that a union contains n objects, where n is the number of members. A union contains only one active object at any point during program execution by §6.7.2.1 ¶16
The value of at most one of the members can be stored in a union object at any time.
Support for this interpretation that a union does not simultaneously contain all of its member objects can be found in §6.5.2.3:
and if the union object currently contains one of these structures
Finally, an almost identical issue was raised in defect report 236 in 2006.
Example 2
// optimization opportunities if "qi" does not alias "qd" void f(int *qi, double *qd) { int i = *qi + 2; *qd = 3.1; // hoist this assignment to top of function??? *qd *= i; return; } main() { union tag { int mi; double md; } u; u.mi = 7; f(&u.mi, &u.md); }Committee believes that Example 2 violates the aliasing rules in 6.5 paragraph 7:
"an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)."
In order to not violate the rules, function f in example should be written as:
union tag { int mi; double md; } u; void f(int *qi, double *qd) { int i = *qi + 2; u.md = 3.1; // union type must be used when changing effective type *qd *= i; return; }