rabson@physics.ubc.ca (David Rabson) (06/25/91)
Until now, I have been content to sit back and ignore the ansi standard for C. Trigraphs are amusing -- I'm almost surprised the IBM representatives on the committee didn't push for including computed gotos as well -- but most compilers turn them off. Eliminating the IDENTA/**/IDENTB concatenation mechanism from the preprocessor was stupid but not enough to make me post to this group. (I am aware of the argument that supports the action, tokenizing compilers, but I am not convinced by it). Outlawing lvalue casts, however, borders on fascism. I have yet to see a pre-ansi compiler that fails to treat properly void *thing; ((int *)thing)++; (or, if it doesn't know about voids, the same thing with char *thing). I realize that some machines might, in principle, have different alignments for different types of pointers. A void *, however, I thought, was guaranteed to obey the most restrictive alignment and hence be castable to any other pointer. I hereby invite the black-shirts from the ansi camp to explain their prejudice against casting lvalues. The rest of us should stop sitting back and start fighting. If enough customers insist on casting lvalues and otherwising ignoring ansi's meddling in Kernighan's and Ritchie's work, vendors will create correct, rather than compliant, compilers. David Rabson Departments of Physics, University of British Columbia and McMaster University
henry@zoo.toronto.edu (Henry Spencer) (06/26/91)
In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >Outlawing lvalue casts, however, borders on fascism. I have yet to see >a pre-ansi compiler that fails to treat properly > > void *thing; > ((int *)thing)++; What do you mean by "treat properly"? What does this construct *mean*? Remember that `void *' and `int *' need not even be the same size, much less have the same representation. A cast is a conversion operation, not a "view these bits differently" operation. (See K&R1 page 42.) >The rest of us should stop sitting back and start fighting. If enough >customers insist on casting lvalues and otherwising ignoring ansi's >meddling in Kernighan's and Ritchie's work, vendors will create >correct, rather than compliant, compilers. Please cite K&R chapter and verse for thinking that casts are lvalues. You might also want to note that Dennis Ritchie has stated openly: "I think X3J11 did an excellent job, though there are legitimate criticisms". (Article <10039@alice.uucp>, 21 Oct 1989.) -- "We're thinking about upgrading from | Henry Spencer @ U of Toronto Zoology SunOS 4.1.1 to SunOS 3.5." | henry@zoo.toronto.edu utzoo!henry
sef@kithrup.COM (Sean Eric Fagan) (06/26/91)
In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >Eliminating the IDENTA/**/IDENTB concatenation >mechanism from the preprocessor was stupid but not enough to make me >post to this group. (I am aware of the argument that supports the action, >tokenizing compilers, but I am not convinced by it). How about this, then: correct C preprocessors replace comments with white space. The Reiser cpp was *broken*, and many, many other implementations existed that did not do that. >Outlawing lvalue casts, however, borders on fascism. I have yet to see >a pre-ansi compiler that fails to treat properly > > void *thing; > ((int *)thing)++; I can think of about 30. Ok, an exaggeration, but I can name at least 5 or 6 that did not do this. You can cast an lvalue. However, the result is no longer an lvalue. What is a compiler supposed to make of: int f; (float)f++; Learn the language. -- Sean Eric Fagan | "What *does* that 33 do? I have no idea." sef@kithrup.COM | -- Chris Torek -----------------+ (torek@ee.lbl.gov) Any opinions expressed are my own, and generally unpopular with others.
bhoughto@hopi.intel.com (Blair P. Houghton) (06/26/91)
In article <1991Jun25.181916.26586@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >>Outlawing lvalue casts, however, borders on fascism. >> void *thing; >> ((int *)thing)++; And then I suppose the next line is ((double *)thing)++; >Remember that `void *' and `int *' need not even be the >same size, much less have the same representation. A cast >is a conversion operation, not a "view these bits >differently" operation. (See K&R1 page 42.) Much less the same location; after the cast the value may be sitting in an accumulator, or in the phase space on the wiring at 14.5 picoseconds antecedent to the accumulator (Cray was a genius, kids, not just another hacker :-)), but not necessarily anywhere near the storage for `thing'. >Please cite K&R chapter and verse for thinking that casts are lvalues. They certainly aren't addressable. >>The rest of us should stop sitting back and start fighting. If enough >>customers insist on casting lvalues and otherwising ignoring ansi's They'll be left behind. I've seen other standards that have had _real_ problems in them, and nobody bothers with them any more. ANSI X3.159-1989, on the other hand, is pretty solid, almost impervious. --Blair "Write when you find a bug."
wittig@gmdzi.gmd.de (Georg Wittig) (06/26/91)
rabson@physics.ubc.ca (David Rabson) writes: > void *thing; > ((int *)thing)++; Why don't you write (*((int**)&thing))++;} ? gcc thinks it's o.k. -- Georg Wittig GMD-Z1.IT P.O.Box 1240 | "Freedom's just another word D-W-5205 St. Augustin 1 (Germany) | for nothing left to lose" email: wittig@gmdzi.gmd.de | (from "Me and Bobby McGee", telephone: (+49) 2241 14-2294 | Janis Joplin, Kris Kristofferson)
jos@and.nl (J. Horsmeier) (06/26/91)
In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: [...] >Outlawing lvalue casts, however, borders on fascism. I have yet to see >a pre-ansi compiler that fails to treat properly > > void *thing; > ((int *)thing)++; > >(or, if it doesn't know about voids, the same thing with char *thing). I >realize that some machines might, in principle, have different alignments for >different types of pointers. A void *, however, I thought, was guaranteed >to obey the most restrictive alignment and hence be castable to any other >pointer. > >I hereby invite the black-shirts from the ansi camp to explain their >prejudice against casting lvalues. [...] >David Rabson >Departments of Physics, University of British Columbia and McMaster University Hi there, I'll die if casting lvals is going to be illegal. Currently I'm fiddling and hacking my way into a FORTRAN (Yuck) program, trying to interface the beast with loads of old C code. One of my most frequent statements is: type* Thing; ((int)Thing)= Thing-Base+1; where Thing points into an array of things and Base is the beginning of the array, just to change pointers into FORTRAN indices. I know this is dirty and things might go into la la land on lots of machines, but it works on the machine it's running on now. I also know that I can overlay different types with unions. But why? Things used to work fine this way (if you know what you're doing). I really like the statement: `You get what you deserve'. Here I get what I want :-) BTW beauty doesn't count when FORTRAN is involved. You have my support on this topic! Jos +----------------------------------------------------------------------+ |O J.A. Horsmeier AND Software B.V. phone : +31 10 4367100 O| |O Westersingel 106/108 fax : +31 10 4367110 O| |O 3015 LD Rotterdam NL e-mail: jos@and.nl O| |O--------------------------------------------------------------------O| |O I am a Hamburger (F. Zappa 1974) O| +----------------------------------------------------------------------+
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/26/91)
In article <rabson.677868220@physics.ubc.ca>, rabson@physics.ubc.ca (David Rabson) writes: > Outlawing lvalue casts, however, borders on fascism. I have yet to see > a pre-ansi compiler that fails to treat properly > > void *thing; > ((int *)thing)++; > > (or, if it doesn't know about voids, the same thing with char *thing). Funny thing, I've been using C since V6+ UNIX (1979), and I have never ever had any reason to use one of these things. If you really want to accomplish the probable intended effect of that, thing = (void*)(1+(int*)thing); is legal, is it not? > I hereby invite the black-shirts from the ansi camp to explain their > prejudice against casting lvalues. It was never part of the language, and this is an area where X3J11 chose not to innovate. If you're going to moan about things which were never explicitly legal vanishing, how about my old favourite? Labels used to be usable as constants of type char*, so I could pass a label in a C function to an assembly-coded function. Great for speeding up threaded-code. But did the ANSI committee support that lovely old hack? No. Sob sob sob. Do I call them "black-shirts" for this? No. > The rest of us should stop sitting back and start fighting. If enough > customers insist on casting lvalues and otherwising ignoring ansi's > meddling in Kernighan's and Ritchie's work, vendors will create > correct, rather than compliant, compilers. It's attitudes like this that make me think about switching to Ada. -- I agree with Jim Giles about many of the deficiencies of present UNIX.
fin@norge.unet.umn.edu (Craig A. Finseth) (06/26/91)
>>Outlawing lvalue casts, however, borders on fascism. I have yet to see >>a pre-ansi compiler that fails to treat properly >> >> void *thing; >> ((int *)thing)++; ... >Hi there, I'll die if casting lvals is going to be illegal. Currently I'm >fiddling and hacking my way into a FORTRAN (Yuck) program, trying to interface >the beast with loads of old C code. One of my most frequent statements is: ... Ok, kids, let's take a deep breath and say this one more time. All together now: The ANSI standard did not create any new illegal constructs. The ANSI standard only said, for the first time and in writing, that certain constructs WHICH NEVER WERE MEANINGFUL IN THE FIRST PLACE are, in fact, not meaningful. Yes, some of these constructs may have worked on certain compilers in certain situations. THAT DOES NOT MEAN THAT THEY EVER WORKED ON ALL COMPILERS IN ALL SITUATIONS IN THE PAST. The fact that you may have never bumped into one of these other compilers is irrelevant. The entire C world is not (pick your favorite) K&R-based, UNIX pcc-based, IBM PC w/ Turbo C, IBM PC w/Microsoft C, a VAX, ... So far, no one has come up with any examples of any of these "meaningful" constructs that are, in fact, meaningful. The recent examples are: construct rewrite as ... ((i = 1) == (i = 2)) ... (i = 1, 0) or (i = 2, 0) q = q++; q = q + 1; or q += 1; or q++; or ++q; void *thing; ((int *)thing)++; (*((int **)(&thing)))++; [ if you must, that is, and I hope that I got this right ] My concluding advice? If you find that you must use a construct like the one on the left, you should refer to your favorite manual and find the construct on the right that you really wanted in the first place. Either that, or put in a comment of the form: /* The following construct is offically undefined. However, on system ______ serial number _______ running OS ________ version _______ release ______ configured as _____________ _________________________________ and using compiler ___________ version ________ release ________ with compilation flags __________ it just happens to work right. For now. And, by the way, what I mean by "right" is ________________ ___________________________________________________________ ________________________________________________________ */ Now, do you see how much is gained by having a standard, following it, and not trying to push the limits too much? Craig A. Finseth fin@unet.umn.edu [CAF13] Networking Services +1 612 624 3375 desk Computer and Information Services +1 612 625 0006 problems University of Minnesota +1 612 626 1002 FAX 130 Lind Hall, 207 Church St SE Minneapolis MN 55455-0134, USA
roy@prism.gatech.EDU (Roy Mongiovi) (06/26/91)
Well, while I can think of easy ways to code around it, they involve extra data movement. I fail to see why the following should be categorically outlawed: char *intptr; intptr = malloc(sizeof(int)); read(fd, intptr, sizeof(int)); *((int *) intptr)++; . . . Admittedly, I can't think of a really great reason why I might want to do that, but one of the major things that I like about C is that the programmer is the boss. -- Roy J. Mongiovi Systems Support Specialist Office of Computing Services Georgia Institute of Technology Atlanta, Georgia 30332-0275 (404) 894-4660 uucp: ...!{allegra,amd,hplabs,ut-ngp}!gatech!prism!roy ARPA: roy@prism.gatech.edu
steve@taumet.com (Stephen Clamage) (06/27/91)
jos@and.nl (J. Horsmeier) writes: >In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >[...] >>Outlawing lvalue casts, however, borders on fascism. I have yet to see >>a pre-ansi compiler that fails to treat properly >> void *thing; >> ((int *)thing)++; >>I hereby invite the black-shirts from the ansi camp to explain their >>prejudice against casting lvalues. >Hi there, I'll die if casting lvals is going to be illegal... Sorry your life has to end so soon, but it is not a question of "going to be illegal", but "has always been illegal." This rule is in K&R 1, so it is nothing that the ANSI committee added out of sadism. It is just that many compilers failed to enforce the rule. We have to differentiate between what works on some architectures and what is suitable in a language definition. Besides, you are only presenting the trivial cases. The issue is that a cast is a value conversion, not just a request to treat a region of memory in a different way. Suppose a cast resulted in an lvalue whenever the object of the cast were an lvalue. Then this would be legal: float f; ((double)f)++; Nothing good could come of allowing code like this. So we would have to add an exception, like when the sizes were different. Of course, the representations might be different even when the sizes were the same, so maybe that should be an exception too. It turns into a real mess. The language already supports what you want to do, leaving in the very proper semantic rule that a cast is a value conversion and does not result in an lvalue. To get the effect you want, just take the address, cast the pointer, and dereference. void *thing; (*((int **)&thing))++; This violates no language rules, so long as "thing" was assigned the address of an int. Otherwise, the code is not portable, but happens to work on common architectures. It is hard to write (and read), however. If you do not have religious beliefs which require that ++ be used whenever possible, you can write the above as thing = (int*)thing + 1; which is legal, portable, and readable. In the common case where the illegal example would have been ok, the generated code should be identical with any decent compiler. -- Steve Clamage, TauMetric Corp, steve@taumet.com
henry@zoo.toronto.edu (Henry Spencer) (06/27/91)
In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >... I'll die if casting lvals is going to be illegal... Sorry to hear of your demise. Casts are not lvalues, and never have been, despite an occasional sloppy compiler that let you get away with it. -- "We're thinking about upgrading from | Henry Spencer @ U of Toronto Zoology SunOS 4.1.1 to SunOS 3.5." | henry@zoo.toronto.edu utzoo!henry
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/27/91)
I don't understand. Is this whole ``call to revolt'' simply because someone can't translate char *x; x += sizeof(int); into void * terminology? Here goes: void *x; x = (void *) (sizeof(int) + (char *) x); Sheesh. By the way, anyone who thinks that the ``safety'' of void * outweighs the portability of char * must live in a very limited environment. (An environment where you write code which only runs on one machine fits my definition of limited.) ---Dan
gwyn@smoke.brl.mil (Doug Gwyn) (06/27/91)
In article <1991Jun25.190854.3327@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes: >Learn the language. Hear, hear. Just because X3J11 didn't do things the way that fellow would have doesn't make X3J11 wrong and him right. In this case, to the contrary.
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)
In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >Hi there, I'll die if casting lvals is going to be illegal. Well, you can cast an lval, but the result is not an lval. I guess you mean you'll die if the result of a cast isn't an lval. I guess you've been dead ever since casts were added to C, around 1978, except for brief intervals on some BSD-based compilers. >type* Thing; >((int)Thing)= Thing-Base+1; You'll die if you have to write Thing = (type*) (Thing-Base+1); My heart bleeds for you. Incidentally, your code would fail if int is smaller than pointers to "type," for example if int is 32 bits and pointers are 48 bits. My suggestion would fail if the implementation is excessively perverse, but not due to reasonable hardware architectures. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)
In article <31822@hydra.gatech.EDU> roy@prism.gatech.EDU (Roy Mongiovi) writes: >I fail to see why the following should be categorically outlawed: > char *intptr; > intptr = malloc(sizeof(int)); This is legal. > read(fd, intptr, sizeof(int)); This is also legal as far as the standard is concerned. If you don't have a prototype in scope, and size_t is not the same size of integer as read() expects for its third parameter, then it could fail at execution time. > *((int *) intptr)++; OK, if people want ++ to be applicable to non-lvalues, submit your suggestions to the committee when they call for comments on C-2001 (the successor to C-1989). For all you people who enjoy doing: void f(int x) { x ++; } f(n); /* Huh? Why didn't the value of n get bumped? */ f(3); /* Huh? Why didn't my 3 change to 4, like in the bad old days of Fortran? */ OK, you should also be allowed to say (n + 13) ++; /* Huh? Why didn't n get bumped? Or should (n+13) have been bumped? ? */ *((int *) intptr)++; /* Huh? Why didn't intptr get bumped? */ -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
bhoughto@bishop.intel.com (Blair P. Houghton) (06/27/91)
In article <782@taumet.com> steve@taumet.com (Stephen Clamage) writes: >jos@and.nl (J. Horsmeier) writes: > >>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >>> void *thing; >>> ((int *)thing)++; > > (*((int **)&thing))++; > thing = (int*)thing + 1; This'll do it, too: thing += (int *)1; (see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and footnote 51 at the bottom of p. 51, for proof...) --Blair "If void* was meant to fly, X3J11 would have given it wings..."
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)
In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes: >>>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes: >>>> void *thing; >>>> ((int *)thing)++; >This'll do it, too: > thing += (int *)1; Oh no, not again. I thought addition of pointers had been beaten to death. >(see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and >footnote 51 at the bottom of p. 51, for proof...) Well, the page numbers are different in the last draft version, and footnote 51 has nothing to do with it, but I still see nothing that hints at the legality of adding two pointers. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
bhoughto@bishop.intel.com (Blair P. Houghton) (06/27/91)
In article <1991Jun27.032834.13244@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes: >Oh no, not again. I thought addition of pointers had been beaten to death. Oh, screw it. I'm going home and getting some sleep. --Blair "If you'd just let me add the damn pointers...did I _ask_ for a lollipop???"
jos@and.nl (J. Horsmeier) (06/27/91)
In article <782@taumet.com> steve@taumet.com (Stephen Clamage) writes: [...] >>Hi there, I'll die if casting lvals is going to be illegal... > >Sorry your life has to end so soon, but it is not a question of "going >to be illegal", but "has always been illegal." This rule is in K&R 1, >so it is nothing that the ANSI committee added out of sadism. It is just >that many compilers failed to enforce the rule. [...] >Steve Clamage, TauMetric Corp, steve@taumet.com Hi there, I know, I know, you're absolutely right, and normally I don't diddle code like I showed in my reply. And I won't die either ... but, currently I am working on an interface between *very* old C code and loads of FORTRAN stuff and I want to finish this project asap. To plough through all this f*ckin' code makes my mind go nuts, and invites one to fiddle/diddle these dirty tricks. I know it's all *absolutely* non-portable, it's dirty and should not be done, but I don't care in this particular case, I just want the thing up and running on just one type of machine, and these kinda tricks allow me to hack things together. I don't want to make a thread out of this, but I won't change my opinion about the `you get what you deserve' philosophy. I like it, if I deserve non-portability, I want to get non-portability. If I deserve segmentation violations, I want to get segmentation violations. It's my own choice. I don't want any committee to forbid things like that in any language. A language is supposed to be a tool to express yourself, the way you want and like to do so :-) Restricting syntactic and/or semantic richness of a language, just to avoid potential abuse by some zomby woofs from outer space is bad practice IMHO :-) See ya! Jos +----------------------------------------------------------------------+ |O J.A. Horsmeier AND Software B.V. phone : +31 10 4367100 O| |O Westersingel 106/108 fax : +31 10 4367110 O| |O 3015 LD Rotterdam NL e-mail: jos@and.nl O| |O--------------------------------------------------------------------O| |O I am a Hamburger (F. Zappa 1974) O| +----------------------------------------------------------------------+
jfw@ksr.com (John F. Woods) (06/27/91)
diamond@jit533.swstokyo.dec.com (Norman Diamond) writes: >In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >>Hi there, I'll die if casting lvals is going to be illegal. >>type* Thing; >>((int)Thing)= Thing-Base+1; >You'll die if you have to write > Thing = (type*) (Thing-Base+1); >My heart bleeds for you. Well, in fact, the second line isn't actually obligated to do what is apparently desired, i.e. to copy the integer value bit-for-bit into the pointer; the cast to a pointer is entitled to (if deemed desirable by the compiler writer) change the representation to something that the hardware would find more convenient. The problem isn't really that J. Horsmeier doesn't understand the subtleties of the language, it's that he doesn't understand the fairly gross problem of portability. To accomplish exactly what this person thinks is desired requires a union, but of course that course is still fraught with peril, because the thing being done is non-portable. The bulk programming community seems to have gone from undergraduate VAX programmers who just don't understand portability issues to geeky 8086 programmers who actively misunderstand portability; thank goodness Intel is trying to exterminate all future microprocessor architectures in favor of their washing-machine controller, or the next generation of programmers might be completely useless! :-)
mcdaniel@adi.com (Tim McDaniel) (06/27/91)
Oh, dear. I had thought this horse had fossilized by now. In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes: This'll do it, too: thing += (int *)1; (see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and footnote 51 at the bottom of p. 51, for proof...) In the ANSI-published version, footnote 51 is at the bottom of page 54, and deals with "the asymmetric appearance of these constraints with respect to type qualifiers" in simple assignment, which means "=". It is therefore entirely irrelevant. Page 51 has no footnotes. Perhaps footnote 46 on page 48 was meant? It deals with pointer arithmetic, but is careful to specify "*integral* expression added to or subtracted from the converted pointer" (emphasis mine). The above-referenced p. 55, ll. 20-21 does say, under "Semantics" of "Compound Assignment": A *compound* *assignment* of the form E1 *op*= E2 differs from the simple assignment expression E1 = E1 *op* (E2) only in that the lvalue E1 is evaluated only once. However, the "Constraints" six lines up read: For the operators += and -= only, either the left operand shall be a pointer to an object type and the right shall have integral type, or the left operand shall have qualified or unqualified arithmetic type and the right shall have arithmetic type. "(int *) 1" does not have integral type; it has pointer type. Pointer types and integral types are clearly distinguished in section 3.1.2.5, "Types". Section 3.3.6, "Additive Operators" (p. 47), (which applies due to the "Semantics" section quoted above) has the constraint For addition, either both operand shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integral type. In section 3.3.4, "Cast Operators", in "Semantics", An arbitrary integer may be converted to a pointer. The result is implementation-defined. \footnote{45. The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.} In short: bullshit. --Tim "More accurately, it's fossilized horseshit." -- "Of course he has a knife; he always has a knife. We all have knives. It's 1183 and we're barbarians." -- Eleanor of Aquitaine, "A Lion in Winter" Tim McDaniel Applied Dynamics Int'l.; Ann Arbor, Michigan, USA Internet: mcdaniel@adi.com UUCP: {uunet,sharkey}!amara!mcdaniel
burley@pogo.gnu.ai.mit.edu (Craig Burley) (06/27/91)
In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
It's my own choice.
Create your own language to make your own choices. But don't try and claim
ANSI C is "wrong" or failed simply because you can't express something that
is meaningless or has a variety of meanings to different people. C already
had enough baggage like that before ANSI got ahold of it. No reason to add
anything new.
I don't want any committee to forbid things like that
in any language.
Then don't use any languages standardized by any committees. Like I said,
create your own language. I've done it when it was appropriate to the task
at hand.
A language is supposed to be a tool to express yourself,
the way you want and like to do so :-)
Wrong. Take a bunch of cans of paint, reach your hands into arbitrary cans,
splatter paint on a canvas or wall, and you have just expressed yourself the
way you want -- but nobody is likely to understand what you are trying to
express. Use a language of expression, whether abstract, symbolic, formal,
whatever, and do it well, and others will be able to understand it. That is
the purpose of language. If you want to do whatever you feel like as far
as "expressing yourself" in a computer language, like I said, write your own,
or at least use assembler (or, better yet, machine code the stuff directly).
But if you want others to be able to understand what you are writing, then
use the language, and learn to use it properly.
Restricting syntactic and/or semantic
richness of a language, just to avoid potential abuse by some zomby woofs
from outer space is bad practice IMHO :-)
I agree, but that's not the case with disallowing
((int) thing)++;
and suchlike. The ONLY "proper" interpretation of the above construct, given
what casts are in C, would be the following:
Get the value of "thing".
Convert that value (a temporary in a register, basically) to type "int".
Increment that temporary.
But you seem to want it to mean something different, like:
Get the value of "thing".
Convert that value to type "int".
Increment the result.
Convert the result back to the type of "thing".
Write the result back to "thing".
Or:
Pretend "thing" really is an integer, and increment that.
These two things can have different results, and certainly they have results
different from the first definition, which does nothing.
Because lots of compilers allow this without warning (failings in those
compilers, perhaps), you can get away with the construct and write nonportable
and even incorrect code. You might even discover that a compiler did something
unexpected with your code. But these compilers can interpret your construct
however they wish, and only if they specifically describe what they do in their
documentation can you legitimately complain about their implementation (if it
is different from their description).
So please stop complaining about ANSI C as if it is restricting something
that should work the way you want, because:
1. ANSI C did not restrict it, the restriction was always there in the
language even if not in all compilers that implemented the language, as
many others have mentioned.
2. The whole point of ANSI C was to create a standard language based on a
variety of dialects called "C" that somehow managed to satisfy a variety
of criteria, primarily the portability of conforming programs to a wide
variety of architectures and the ease of conversion from the various
old dialects to the new standard language. I believe it is reasonable to
state that none of the individual criteria were satisfied 100%, but that
the degree of satisfaction is higher for the criteria they deemed more
important (at least for the most part). It certainly is true that no
language definition could have satisfied all the criteria 100%.
3. The construct you show can be interpreted in a variety of ways by various
experienced C programmers, as I illustrated above, and one of those
interpretations is thoroughly nonportable, another is entirely out of the
mold of C (the idea of storing a compiler-generated temporary back into
its source location, without explicitly specifying an lvalue for the
destination, does not exist in C, to my knowledge), and the other (the one
I claim is most natural) is completely useless.
4. There are better (more portable, more readable) ways to do what you want.
(By "more readable" I do NOT mean "expressed in fewer characters", but
"expressed within a subset of the language understood by a greater number
of people compared to using a specific but rarely used construct". For
example, the phrase "Avoid making things more obscure than necessary" is
more readable, despite being longer, than "Eschew obfuscation", even though
the latter is funnier (once you look up the words) and, to the minority
with a large enough vocabulary, more to the point.)
ANSI C has some dumb things about it (trigraphs spring immediately to mind...
OUCH! :-), but disallowing this construct is NOT one of them.
--
James Craig Burley, Software Craftsperson burley@gnu.ai.mit.edu
gwyn@smoke.brl.mil (Doug Gwyn) (06/28/91)
In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes: > thing += (int *)1; No, this doesn't work.
gwyn@smoke.brl.mil (Doug Gwyn) (06/28/91)
In article <4247@ksr.com> jfw@ksr.com (John F. Woods) writes: >To accomplish exactly what this person thinks is desired requires a union, I don't know exactly what that person thinks, if anything, but certainly a union would not solve anything. It would make things much worse in the case of an implementation that represents different pointer types differently. The simple solution is to use a char* or void* as a "generic pointer" and deal with the address arithmetic oneself. This is really quite simple and doesn't need to be hashed over in this (C standards) newsgroup. It is not a standards issue.
bhoughto@pima.intel.com (Blair P. Houghton) (06/28/91)
In article <16560@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes: >> thing += (int *)1; > >No, this doesn't work. Not as a line of conforming code, no. And yes, I did have a good (~3hr) nap. --Blair "Makes one HELL of an alligator repellent, though..."
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/28/91)
In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >And I won't die either ... Glad to hear it. >I don't want to make a thread out of this, but I won't change my opinion >about the `you get what you deserve' philosophy. >I like it, if I deserve non-portability, I want to get non-portability. OK, you asked for non-portability, you got non-portability, and you say you wanted to get non-portability. So why are you complaining here? Your code works on your old compiler, and either it won't port to your new ANSI-conformant compiler or else it will port with a diagnostic message. You got your non-portability. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/28/91)
In article <4247@ksr.com> jfw@ksr.com (John F. Woods) writes: >diamond@jit533.swstokyo.dec.com (Norman Diamond) writes: >>In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >>>Hi there, I'll die if casting lvals is going to be illegal. >>>type* Thing; >>>((int)Thing)= Thing-Base+1; >>You'll die if you have to write >> Thing = (type*) (Thing-Base+1); >>My heart bleeds for you. > >Well, in fact, the second line isn't actually obligated to do what is >apparently desired, i.e. to copy the integer value bit-for-bit into the >pointer; Yeah, well neither is the first line. The first line intuitively should not copy anything at all into the pointer, and legally can erase his hard disk after issuing a diagnostic. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
jos@and.nl (J. Horsmeier) (06/28/91)
In article <BURLEY.91Jun27120009@pogo.gnu.ai.mit.edu> burley@pogo.gnu.ai.mit.edu (Craig Burley) writes: >Create your own language to make your own choices. But don't try and claim >ANSI C is "wrong" or failed simply because you can't express something that >is meaningless or has a variety of meanings to different people. C already >had enough baggage like that before ANSI got ahold of it. No reason to add >anything new. I don't claim ANSI C is wrong, I was simply replying to a 'call to revolt', 'cause (I repeat myself), I like the philosophy: `You get what you deserve', and given the hypothetical assumption that ANSI C was `going to forbid lvalue casts' (read the original posting), I responded, that's all :-) > I don't want any committee to forbid things like that > in any language. > >Then don't use any languages standardized by any committees. Like I said, >create your own language. I've done it when it was appropriate to the task >at hand. > Why should any committee forbid, non-portable, non-clearly-defined tricks etc. offered by any language. Ripping these things out of a language is not doing any good to that language. I *do* like the idea of commitment to a standard as long as this standard simply enumerates all these non-portability pitfalls and still allows one to use these hacks. Sometimes these things come in handy on particular hardware environments, as long as you *know* and *realize* that you're hacking close to the edge. > A language is supposed to be a tool to express yourself, > the way you want and like to do so :-) > >Wrong. Take a bunch of cans of paint, reach your hands into arbitrary cans, >splatter paint on a canvas or wall, and you have just expressed yourself the >way you want -- but nobody is likely to understand what you are trying to [...] No, as long as we are using the same tool (language), we can understand each other. If both parties conform to the rules of the tool, they can communicate the way they want. Even when a sentence contains syntactic or semantic errors, people are capable of understanding each other. (This sentence contains two errors). > > ((int) thing)++; > >and suchlike. The ONLY "proper" interpretation of the above construct, given >what casts are in C, would be the following: > > Get the value of "thing". > Convert that value (a temporary in a register, basically) to type "int". > Increment that temporary. > >But you seem to want it to mean something different, like: > > Get the value of "thing". > Convert that value to type "int". > Increment the result. > Convert the result back to the type of "thing". > Write the result back to "thing". [...] Yep, that's exactly what I want (only with the stuff I'm currently working on). I want an integer value plugged into the memory locations, previously containing a pointer value. I know what I'm doing, I know it's not portable, I know about different pointer sizes, I know it's not ethical, etc. etc. etc. :-) I know it can be done `the neat way', but all I want is a quick hack to do the job, and I love it if a language gives me the opportunity to do so. The stuff I'm working on now is not supposed to be portable, it's a dead end anyhow, they just want the beast up and running for about six more months, afterwards they let it die peacefully, so why bother about standards? > >So please stop complaining about ANSI C as if it is restricting something [...] I'm not complaining about ANSI C. I like it when committees try to make things explicit and `clear'. It can be a great help. Hidden language `features' are a mess: define and elucidate them, but don't forbid them (which was the original assumption). Label them as dangerous, bad practice or whatever and clarify to the zomby woofs who still want to use them, that they're naughty boys and girls =8^) > >ANSI C has some dumb things about it (trigraphs spring immediately to mind... >OUCH! :-), but disallowing this construct is NOT one of them. Who wants trigraphs anyway? >James Craig Burley, Software Craftsperson burley@gnu.ai.mit.edu And please, let's not make a thread out of this, it's not worth the trouble. See ya, Jos +----------------------------------------------------------------------+ |O J.A. Horsmeier AND Software B.V. phone : +31 10 4367100 O| |O Westersingel 106/108 fax : +31 10 4367110 O| |O 3015 LD Rotterdam NL e-mail: jos@and.nl O| |O--------------------------------------------------------------------O| |O I am a Hamburger (F. Zappa 1974) O| +----------------------------------------------------------------------+
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/28/91)
In article <998@baby.and.nl>, jos@and.nl (J. Horsmeier) writes: > And I won't die either ... but, currently I am working on an interface > between *very* old C code and loads of FORTRAN stuff and I want to finish > this project asap. To plough through all this f*ckin' code makes my > mind go nuts, and invites one to fiddle/diddle these dirty tricks. The ANSI committee has done *nothing* to stop you. > I know it's all *absolutely* non-portable, it's dirty and should not be done, > but I don't care in this particular case, I just want the thing up and running > on just one type of machine, and these kinda tricks allow me to hack things > together. The ANSI committee has done *nothing* to stop you. What's really tragic about this, of course, is that the examples I've seen so far were all things that could have been written portably in the first place. > I like it, if I deserve non-portability, I want to get non-portability. > It's my own choice. I don't want any committee to forbid things like that > in any language. The ANSI committee has done *nothing* to stop you. We're talking here about a feature which was always illegal according to K&R1, but some compilers let you do it anyway. So it wasn't portable. We're talking about a feature which is not explicitly permitted by ANSI. Has the ANSI committee *forbidden* any vendor to implement L-value casts? *NO*! Any vendor that wants to can implement L-value casts. (I keep trying to write that as "L-value costs". Too apt.) And then your program can use them. And it won't be portable. In short, nothing has changed. Remember, all that a standard does is say to a programmer "this is all that you can rely on" and to a vendor "this is all you are obliged to provide". Standards don't, and can't, say to programmers "this is all that you are allowed to use in any implementation" or to a vendor "you may not provide more than this". Don't accuse ANSI of forbidding an unnecessary extension when all they did was refrain from requiring it! -- I agree with Jim Giles about many of the deficiencies of present UNIX.
gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)
In article <4909@inews.intel.com> bhoughto@pima.intel.com (Blair P. Houghton) writes: -In article <16560@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: ->In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes: ->> thing += (int *)1; ->No, this doesn't work. -Not as a line of conforming code, no. It requires a diagnostic!! -And yes, I did have a good (~3hr) nap. Try a ~3yr nap.
sef@kithrup.COM (Sean Eric Fagan) (06/29/91)
I've got a bone to pick with X3J11, as well! I had some code that worked *fine* with my *K&R* compiler, but doesn't work with the ANSI compiler I got. The following *used* to work, but now doesn't! I can't understand *how* ANSI could even *begin* to define a language that *breaks* existing code! int foo(a, b) int a, b; { int tmp; /* some stuff */ tmp = a*b; } main() { printf ("%d\n", foo(10, 20)); } I think we should all start a letter-writing campaign to protest how X3J11 *broke* C! ---- Editor's note: the posted example is true, only the code has been simplified to protect the innocent. A certain version of Microsoft C for Xenix '386 performed the multiply, and left the result in %eax. A certain version of GCC, seeing that the result was not returned, did not perform the multiplication, therefore a random value was left in %eax. The author of the code is now serving maximum sentence in a COBOL shop. ---- -- Sean Eric Fagan | "What *does* that 33 do? I have no idea." sef@kithrup.COM | -- Chris Torek -----------------+ (torek@ee.lbl.gov) Any opinions expressed are my own, and generally unpopular with others.
jos@and.nl (J. Horsmeier) (06/29/91)
In article <1991Jun28.040420.28730@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes: >In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >>And I won't die either ... > >Glad to hear it. > [My silly stuff here ...] > >OK, you asked for non-portability, you got non-portability, and you say >you wanted to get non-portability. So why are you complaining here? >Your code works on your old compiler, and either it won't port to your >new ANSI-conformant compiler or else it will port with a diagnostic >message. You got your non-portability. >-- Hi, please let's stop this silly discussion. Once and for all, I am *not* complaining. Someone made the assumption of the ANSI C comittee forbidding lvalue casts, and started a `call to revolt'. I replied, 'cause I liked the subject. Ripping non-portable `features' out of a language is not doing any good to that language. Warning people and making them aware of these non- portable, dirty ga-ga's *is* doing some good to a language (like X3J11 does). But, if (and only if) portability is not a concern (like in my current situation, I hope it'll change soon), why not stick ints into pointers with a quick hack? Who cares? I know, char p; *((double*)&p)= 1.2345; could, and probably will, kill your program. I know, I know, it's all ever so simple. I know of hundreds of different situations that are *not* portable or just made possible by a flaw in the compiler, or have only rights to exist on zomby machines. And most of the time I don't use them! But, for all sake, don't amputate them from a language (which was the original assumption). Just advice people not to use them, and if they still want to: They get what they deserve! Good for them. On the other hand, if you know what you're doing, who is entitled to forbid you from doing so? But anyhow, this became a thread already, let's stop it and talk about nicer things. This is moving from nowhere into la la land. See ya! 8^) Jos +----------------------------------------------------------------------+ |O J.A. Horsmeier AND Software B.V. phone : +31 10 4367100 O| |O Westersingel 106/108 fax : +31 10 4367110 O| |O 3015 LD Rotterdam NL e-mail: jos@and.nl O| |O--------------------------------------------------------------------O| |O while (1) *((int*)rand())= rand(); /* Why does it a core dump? */ O| +----------------------------------------------------------------------+
jos@and.nl (J. Horsmeier) (06/29/91)
In article <1991Jun28.220128.22032@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes: >I've got a bone to pick with X3J11, as well! I had some code that worked [Yuck code deleted ...] > >I think we should all start a letter-writing campaign to protest how X3J11 >*broke* C! >---- >Editor's note: the posted example is true, only the code has been [...] >multiplication, therefore a random value was left in %eax. The author of >the code is now serving maximum sentence in a COBOL shop. ^^^^^ Try OBJECT-ORIENTED-COBOL, Like C++ they've called it: ADD ONE TO COBOL GIVING COBOL +----------------------------------------------------------------------+ |O J.A. Horsmeier AND Software B.V. phone : +31 10 4367100 O| |O Westersingel 106/108 fax : +31 10 4367110 O| |O 3015 LD Rotterdam NL e-mail: jos@and.nl O| |O--------------------------------------------------------------------O| |O MOVE CORRESPONDING SH*T TO TOILET BEFORE FLUSHING ONE LINE O| +----------------------------------------------------------------------+
gwyn@smoke.brl.mil (Doug Gwyn) (06/30/91)
In article <1015@baby.and.nl> jos@and.nl (J. Horsmeier) writes: >This is moving from nowhere into la la land. It started in la-la land.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/30/91)
In article <1015@baby.and.nl>, jos@and.nl (J. Horsmeier) writes: > Hi, please let's stop this silly discussion. > Once and for all, I am *not* complaining. ^^^^^^^^^^^^^^^^^^^^^^ > Ripping non-portable `features' out of a language is not doing any > good to that language. ... > But, for all sake, don't amputate them from a language > (which was the original assumption). If this isn't a complaint, it will do until the real thing comes along. The thing which some posters seem to have difficulty grasping is that X3J11 DID NOT RIP L-VALUE CASTS OUT OF THE LANGUAGE. You might as well complain that they removed the `max' and `min' operators from the language! Fact: there were a couple of compilers around that provided infix operators /\ and \/. I _loved_ those operators; even fixed one of the compiler so they worked. That was a non-portable feature in *precisely* the same sense as L-value casts. We're not talking here about an operation which wasn't well defined (like right shift of signed integers, or the rules for combining signed and unsigned), we're talking about features which, although _some_ compilers had them, were NEVER part of "Classic C". I wish that /\ and \/ were in ANSI C, but I don't whine about X3J11 "ripping them out of the language", and although it is far less trivial to reorganise code to do without /\ and \/ than to do without L-value casts (which don't even let you abbreviate by more than a couple of characters), I don't accuse X3J11 of "amputating" the wings on that pig. -- I agree with Jim Giles about many of the deficiencies of present UNIX.