ln said:
On a platform where sizeof (void) != sizeof(int), given code like the following:
void is an incomplete type that cannot be completed.
It is not valid to use the operator sizeof on (void).
sizeof(void) is meaningless, and if anything that follows depends on it,
the that too is meaningless. For your question below it is not
sizeof(void) which is used, but sizeof(void *), which is just fine.
There is a huge difference between a pointer-to-void and void.
#include <stdio.h>
union
{
void* p;
int i;
} u;
void f()
{
int* pi = & u.i;
(*pi)++;
u.p = NULL;
}
The effect of the above is to make u.p a null pointer; anything done to
u.i before that produces nothing meaningful.
is the compiler allowed to emit assembly corresponding to:
void f()
{
int* pi = & u.i;
u.p = NULL; // reordered
(*pi)++;
}
Of course not. The effect is quite obviously other than to make u.p
null. NULL might be 0, or it might be (void &)0. Don't assume that the
bit pattern resulting from that assignment is the same as (int)0.
Whatever NULL is, assuming accessing it in this way is licit, the result
cannot be the same null pointer constant, can it?
and is it guaranteed that NULL-ing u.p results in u.i == 0?
NULL
Of course not. Only the value of the last member into which something
is stored has meaning. When the last member to have a value assigned to
it is u.p, reading u.i yields nothing meaningful.
Write this on your forehead: "Only one member of a union can contain a
value at a particular time." Your C text should have a sentence similar
to that. An example of such a statement is in H&S 5.7.4 (Mis)using
Union Types: "Unions are used in a nonportable fashion any time a union
component is reference when the last assignment to the union was not
through the same component."
Tricks involving assigning values to one member and attempting to access
the result of such assignment through another member are tricks that
fledgling programmers should grow out of.