🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c
Article #3453

Re: (no subject) [cast expression as an lva

#3453
From: Chris Torek
Date: Wed, 11 Oct 1995 04:40
66 lines
3462 bytes
>>>       ((char *)src)++;        /* src is an (int *) */

In article t78@inferno.mpx.com.au, msmith@jolt.mpx.com.au (Michael Smith)
writes:
>>I **THINK** that this was considered legal using K&R1 style C.

No, this was never legal.

In article <45ef3f$n8u@engnews2.eng.sun.com> Steve Clamage
<clamage@Eng.Sun.COM> answers:
>K&R1 said that a cast yielded a value, not an lvalue. [Stephen
>Johnson's] PCC compiler did not check for this violation, and the
>code it generated happened to do what the programmer intended. ...
>I don't know what would have happened if the programmer wrote
>	float f;
>	(double)f = 10.0; /* will the compiler complain? */
>	long l;
>	(short)l = 5; /* how about this? */

PCC stored information about expressions in `trees'.  Each tree node
represented something in the source, such as a constant, a variable,
an assignment operator, or a conversion.  There were in fact two kinds
of conversion nodes, SCONV (a `scalar conversion') and PCONV (a
`pointer conversion').

A number of the optimization passes removed unnecessary conversions,
so that the code generator did not have to have templates such as `to
convert from int to int, emit no code'.  On most machines, many (or
even all) PCONV conversions could be removed by rewriting the pointer
type.  Unfortunately, one such conversion remover ran *before* semantics
checking (directly from buildtree(), I believe).  This saved runtime
space and time at the expense of error checking.  By the time the
increment operator handler looked at the `((char *)src)++' tree,
the cast was gone and the tree simply claimed that the goal was to
increment the variable `src' with the type `char *'.

Thus, the answer is that the above two casts (which use SCONV nodes
and change the size and representation as well as the type) were not
removed, and the compiler would complain.

>... instead of 
>	((char*)src)++;
>you can write
>	(*(char**)(&src))++;

If `src' has type `int *' and this is a Data General Eclipse,
`(*(char **)&src)++;' adds 2 bytes to `src'.  On such a machine,
PCC would retain the PCONV node would therefore have complained.

Thus, in effect, PCC defined an lvalue cast as: `Do the cast if
and only if the cast generates no code.'  There is no such construct
in portable C.  On the other hand, no one really *wants* such an
operation.  What they usually *want* is the equivalent of:

	src = (int *)((char *)src + 1);

(still assuming `src' has type `int *').  Of course, on the DG,
this leaves `src' unchanged, because adding one byte to a word
still leaves you pointing to the same word.  In other words, this
code is hopelessly broken; the only thing that can be done with
it is to throw it away.
-- 
In-Real-Life: Chris Torek, Berkeley Software Design Inc
Berkeley, CA	Domain:	torek@bsdi.com	+1 510 549 1145
  `... if we wish to count lines of code, we should not regard them as
   ``lines produced'' but as ``lines spent.'' '  --Edsger Dijkstra
Technical Details
Message-ID: <45fhs8$2ra@elf.bsdi.com>
Path: arc1-ca.pugleaf.net!cs.umd.edu!not-for-mail
References: <45e68p$t78@inferno.mpx.com.au> <45ef3f$n8u@engnews2.eng.sun.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!cs.umd.edu!not-for-mail
From: torek@elf.bsdi.com (Chris Torek)
Newsgroups: comp.std.c,comp.lang.c,comp.unix.solaris
Subject: Re: (no subject) [cast expression as an lva
Date: 10 Oct 1995 21:40:40 -0700
Organization: Berkeley Software Design, Inc.
Distribution: inet
Message-ID: <45fhs8$2ra@elf.bsdi.com>
References: <45e68p$t78@inferno.mpx.com.au> <45ef3f$n8u@engnews2.eng.sun.com>
Reply-To: torek@bsdi.com
NNTP-Posting-Host: elf.bsdi.com