More on the topic of type-punning being problematic:
C23 added constexpr
and new rules as to how compile-time constants can be created and handled. We can now access members of structures and unions as compile-time constants, provided said structures and unions are compile-time constants themselves:
constexpr struct {
int x;
} s = {10};
switch (some_var) {
case s.x:
// ...
}
static_assert(s.x == 10);
static int x = s.x;
// All of the above should be valid
However there is one notable exception:
If the member-access operator . accesses a member of a union constant, the accessed member shall be the same as the member that is initialized by the union constant's initializer.
This essentially has the effect of preventing compile-time type puns. In addition to preventing determining characters in a string at compile-time but that is story for another time.
But what is the rationale for this? What prevents the language from simply defining the behavior to yield the same value that would be yielded at runtime? Why would a compile-time type-pun be anymore problematic than a runtime type-pun? Why would a language allow one but not the other?