Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!caip!rutgers!husc6!mit-eddie!genrad!decvax!ucbvax!cartan!brahms!desj From: desj@brahms (David desJardins) Newsgroups: net.lang.c Subject: Re: Must casting destroy lvalueness? Message-ID: <55@cartan.Berkeley.EDU> Date: Thu, 23-Oct-86 07:01:44 EDT Article-I.D.: cartan.55 Posted: Thu Oct 23 07:01:44 1986 Date-Received: Fri, 24-Oct-86 08:15:55 EDT References: <4617@brl-smoke.ARPA> <657@dg_rtp.UUCP> Sender: daemon@cartan.Berkeley.EDU Reply-To: desj@brahms (David desJardins) Organization: Math Dept. UC Berkeley Lines: 75 Summary: No. In article <4617@brl-smoke.ARPA>, NET-RELAY.ARPA>@brl-smoke.ARPA writes: > For example, a useful and readable way to move a pointer > through a buffer containing a mixture of objects of different sizes is > > ((OBJECT)pointer)++ In article <252@BMS-AT.UUCP> stuart@BMS-AT.UUCP (Stuart D. Gathman) writes: >A more correct syntax: > >{ > char *pointer; > /* . . . */ > pointer += sizeof (OBJECT); > /* . . . */ >} > >And clearer to boot if you ask me. Wrong if you ask me. First, in the original example it is clear that OBJECT is a pointer type. And second, your sample code does not work, and can not readily be fixed, if sizeof (char) != 1. In article <657@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes: >I sayeth that if thou wishest to taketh an object as a different typeth, >thou mayest do so. However, casts are not the way to do this in C, and >the practice is not portable. If you must take the bits of one pointer >type as being those of another pointer type, use > > (*((some_type **)&p))++ In C, pointers and lvalues are the same thing (there is a bijection given by & and *). Essentially, = (and the other assignment operators) automatic- ally take the address of their left-hand arguments, in much the same way that setq/set! quote their first arguments. In both cases this is done simply to enhance readability and reduce mistakes; x = x+1 is clearer and less error- prone than &x <- x+1 would be [store x+1 in the location &x], just as (setq x (+ x 1)) is clearer and less error-prone than (set (quote x) (+ x 1)). Without this syntactic sugar, the situation would be clearer. The C statement (foo) x = ... can correspond either to &((foo) x) <- ... or to (foo *) (&x) <- ..., depending on when the implicit address calculation takes place. Since only the latter makes any real sense, I submit that casting of lvalues should be interpreted in this way. So I would conclude that the statement ((OBJECT) pointer)++ should be interpreted as * ((OBJECT *) &pointer) = (OBJECT) pointer + 1; It is not absolutely clear that this is equivalent to Wayne Throop's alternative formulation (* ((OBJECT *) &pointer))++, which would give * ((OBJECT *) &pointer) = * ((OBJECT *) &pointer) + 1; or to the standard C construction for this type of operation, which is pointer = (char *) ((OBJECT) pointer + 1); But in any implementation in which casting of pointers works at all, I think that these should almost certainly give the same result. At any rate they are all legal C. >or use unions like God intended. Don't try to pervert casts to do >something they weren't intended for. Casts convert, unions take-as. >The take-as operation is inherently non-portable. But the point is that casts of pointers *don't* convert. Either they simply take-as, or they are meaningless. So, if the language allows casting of pointers, then I see no valid reason to complain when the programmer uses this feature (especially since essentially all C implementations make it impossible to avoid when using any sort of dynamic memory allocation!). And if he is allowed to use casting, why force him to write *((foo *) &x) = when (foo) x = will do? At any rate, I think that the answer to the question "*Must* casting destroy lvalues?" is clearly "No." -- David desJardins