another lesson in "portability"
donn at sdchema.UUCP
donn at sdchema.UUCP
Sat Jun 4 12:04:09 AEST 1983
Reference: mit-eddi.218
mit-eddie!mp brings up an interesting issue of portability:
I had some problems compiling some V7 code on 4bsd; wherever
the author had expressions such as "(char *)ptr_to_struct =
ptr_to_char", the compiler complained.
The intuition here is that the left hand side should be interpreted as
using the variable ptr_to_struct as a character variable, but in some
sense it is still the same variable; you should be able to assign to
it, for example. Unfortunately this intuition is false. This is not
entirely clear from the text; as mit-eddie!mp notes, K&R say on p. 42:
...[E]xplicit type conversions can be forced ("coerced")
in any expression with a construct called a cast. In the
construction
( type-name ) expression
the expression is converted to the named type by the conversion
rules [on p. 41]. The precise meaning of a cast is in fact as
if [the] expression were assigned to a variable of the
specified type, which is then used in place of the whole
construction.
The inference which the writer of the V7 programs made is that the
"temporary variable" has the same address as the operand of the cast
and hence it is reasonable to assign to it. However, this inference is
not as reasonable as it might look. For example, what should the
compiler do with this?
int i;
(double) i = 3.141592654;
A double on most machines is considerably larger than an int. If the
compiler treats the cast as being a double with the same address as i,
then whatever follows i in memory is going to get clobbered. One might
argue that this is an expected side-effect which users should know to
look out for, but it seems pretty dangerous to me, especially when
there is a more explicit syntax that accomplishes the same thing:
* (double *) & i = 3.141592654;
I think the inference arises because we 'know' that a conversion of
pointer types does not change the value of a pointer. Needless to say,
this is external to the problem of interpreting casts, and it probably
isn't portable either.
The actual grammar of C in K&R bears out the interpretation that a cast
should not be assigned to. A cast is explicitly an expression, not an
lvalue, and only lvalues may be assigned to; thus the PCC (the VAX
compiler) is actually doing the right thing. (Even though lvalues and
expressions are not distinguished in the PCC's YACC grammar! Lvalues
are found during the static semantics checking.) I still don't know why
Dennis Ritchie's compiler lets these casts through.
At any rate the "correct" way of writing expressions like
(char *) ptr_to_struct = ptr_to_char;
is
ptr_to_struct = (struct foo *) ptr_to_char;
I think this looks better too...
Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn
(619) 452-4016 sdamos!donn at nprdc
More information about the Comp.lang.c
mailing list