Call me Mr. Deer-in-Headlights, but I'd always been taught that
p;
is a no-op.
It's not a no-op from the viewpoint of the standard. Rather, it
calculates the value of variable `p'. Because the value of
variable `p' is indeterminate (see C99 6.2.4#2) and thus may be a
trap representation (see C99 3.17.2), that expression invokes
undefined behavior.
Furthermore, how about:
if (p=malloc(1)) {
int x = (int)p;
free(p);
x;
}
No pointer is involved, so if the conversion `(int) p' produced
a value that is not a trap representation, it is still not a trap
representation after the free().
Casting a pointer to an int is implementation-defined (but not
undefined), isn't it?
Not necessarily, see C99 6.3.2.3#6:
If the result cannot be represented in the integer type, the
behavior is undefined.
There does not seem to be much difference between the above, and
if (p=malloc(1)) {
free(p);
int x = (int)p;
x;
}
That's undefined too, because the value of `p' is still being
accessed. You could access the bytes in `p' through a character
pointer if you like, though.
My rationale: the reason it's undefined to use a pointer value (without
dereferencing) is for systems where loading such a value to a memory
access register causes an exception.
That's a reasonable reason.
However, if we are just converting to int, that register would
not have to be used.
But it's not required not to be used. Behavior is still
undefined.