bbc@titan.rice.edu (11/03/88)
I just read about left-hand side casts in the Internals of GNU CC, and was wondering how everyone else feels about them. They seem odd to me, as if most of their uniqueness from traditional casts won't often be used. Rather, I feel that they would typically be used for clarity, as a substitute for wrapping the whole right-hand side in parentheses and a cast. As an example, with "char *a" as in the section 5.4: a = (char *)( some complicated expression containing many parens) becomes (char *)a = some complicated expression containing many parens I haven't used left-hand side casts, or gcc, and so this is all intuition. Any comments from experienced users? Apologies if this has already been hashed. Ben Chase bbc@rice.edu Computer Science Dept.
jgm@k.gp.cs.cmu.edu (John Myers) (11/17/88)
"Casts as lvalues" is the one extension that I seriously object to. The semantics are not obvious (I had to read the description in the manual three times before I understood what was going on) and are certainly not what the people who have asked for lvalue casts in comp.lang.c were asking (which is good--they generally didn't know what they were talking about anyway.) The extension adds no power to the language, given the typeof operator. (int)a = b is the same as: (int) (a = (typeof a) (int) b) After having looked at a piece of code that used this extension and had also #ifdef's for compilers without this extension, I must say that the traditional code is more readable. (If anyone is interested, the other extension that I object to, but not quite so strongly is "Arithmetic on void-pointers and function pointers". If someone is manipulating byte-sized quantities, they should make it obvious by casting the pointers to char and back. I'd rather have the compiler yell at me when I try to manipulate a void pointer--those buggers are SUPPOSED to be opaque.) -- _.John G. Myers Internet: John.Myers@cs.cmu.edu LoseNet: ...!seismo!inhp4!wiscvm.wisc.edu!give!up "The world is full of bozos. Some of them even have PhD's in Computer Science" --
blarson@skat.usc.edu (Bob Larson) (11/20/88)
They are a documented bug. In very rare situations, they may be used to eliminate a declared temporary by making your code less readable and less portable. (They always have the latter effects.) -- Bob Larson Arpa: Blarson@Ecla.Usc.Edu blarson@skat.usc.edu Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson Prime mailing list: info-prime-request%ais1@ecla.usc.edu oberon!ais1!info-prime-request
lewie@EE.ECN.PURDUE.EDU (Jeff Lewis) (11/23/88)
Re: left-hand side casts First, the name is awkward, how 'bout we call 'em lvalue casts? (where an lvalue is as described in the C book; roughly speaking, something to which you can assign a value.) But anyway, ... > They are a documented bug. In very rare situations, they may be > used to eliminate a declared temporary by making your code less > readable and less portable. (They always have the latter effects.) I'm not attempting to justify the addition of various non-standard features to an implementation of a language, however I think the lvalue cast is getting a bad rap here. Say you needed to push arbitrary sized data onto a stack: int *sp, foo; short int *sp2, bar; unsigned char *sp3, biff; *sp++ = foo; sp2 = (short int *) sp; *sp2++ = bar; sp3 = (unsigned char *) sp2; *sp3++ = biff; sp = (int *) sp3; ... given lvalue casts: int *sp, foo; short int bar; unsigned char biff; *sp++ = foo; *((short int *) sp)++ = bar; *((unsigned char *) sp)++ = biff; even better, much more direct and descriptive of what's going on: (here caddr_t is used in the sense of any valid pointer type of proper alignment for all values to be pushed on the stack) caddr_t sp; long int foo; short int bar; unsigned char biff; *((long int *) sp)++ = foo; *((short int *) sp)++ = bar; *((unsigned char *) sp)++ = biff; Now, obviously this isn't the kind of thing you're going to code everyday, but when, and if, you do, I find the lvalue cast much preferable to the indirection induced by the unnecessary temporaries. --Jeff Lewis (lewie@ee.ecn.purdue.edu, pur-ee!lewie)
david@sun.uucp (David DiGiacomo) (11/23/88)
In article <8811221620.AA25541@ee.ecn.purdue.edu> lewie@EE.ECN.PURDUE.EDU (Jeff Lewis) writes: >Say you needed to push arbitrary sized data onto a stack: > > int *sp, foo; > short int *sp2, bar; > unsigned char *sp3, biff; > > *sp++ = foo; > sp2 = (short int *) sp; > *sp2++ = bar; > sp3 = (unsigned char *) sp2; > *sp3++ = biff; > sp = (int *) sp3; > ... This is not a good example to support the use of lvalue casts. Ordinary rvalue casts will clean it up nicely. #define PUSH(sp, item) \ (* (typeof (item) *) (sp) = (item), ((sp) += sizeof (item))) caddr_t sp; int foo; short int bar; unsigned char biff; PUSH(sp, foo); PUSH(sp, bar); PUSH(sp, biff); ... The poster you quoted was probably referring to something like (type) complicated_expression++ = item; where it's undesirable to realize the complicated_expression twice.