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

		( 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

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;


	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