I\'ve read various posts on Stack Overflow RE: the derefercing type-punned pointer error. My understanding is that the error is essentially the compiler warning of the danger of
This code is invalid per the C Standard, so it might work in some cases, but is not necessarily portable.
The "strict aliasing rule" for accessing a value via a pointer that has been cast to a different pointer type is found in 6.5 paragraph 7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
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 *obj = NULL;
statement, the object has effective type Foo*
but is accessed by the lvalue expression *obj
with type void*
.
In 6.7.5.1 paragraph 2, we have
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
So void*
and Foo*
are not compatible types or compatible types with qualifiers added, and certainly don't fit any of the other options of the strict aliasing rule.
Although not the technical reason the code is invalid, it's also relevant to note section 6.2.5 paragraph 26:
A pointer to
void
shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.
As for the differences in warnings, this is not a case where the Standard requires a diagnostic message, so it's just a matter of how good the compiler or its version is at noticing potential issues and pointing them out in a helpful way. You noticed optimization settings can make a difference. This is often because more information is internally generated about how various pieces of the program actually fit together in practice, and that extra information is therefore also available for warning checks.