chu@acsu.buffalo.edu (john c chu) (03/17/91)
In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: [concerning "if ( a = b )" >Certainly it >is a legal construction, but 90% of the time when I do this it >was my mistake! It's been my mistake everytime I've done it!! I realize that it is a legal construction and I know what it does, but I was wondering... Is there a good use for this? john chu@autarch.acsu.buffalo.edu
sven@cs.widener.edu (Sven Heinicke) (03/18/91)
In <65837@eerie.acsu.Buffalo.EDU>, chu@acsu.buffalo.edu writes: >In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: >[concerning "if ( a = b )" > >It's been my mistake everytime I've done it!! I realize that it is a >legal construction and I know what it does, but I was wondering... >Is there a good use for this? > I went through some of the programs that I wrote and here is probely the best example of a good use for it that was kind of easy to understand (if finds the greatest common demonator of a and b). You can write the program without in in the while statment but it was the easest place I could find to put it. int gcd(a,b) int a,b; { int r,q; while(r = a%b) { q = a/b; a = b; b = r; } return(b); } -- sven@cs.widener.edu Widener CS system manager Sven Mike Heinicke and Student (pssmheinicke@cyber.widener.edu (if you must))
dave@cs.arizona.edu (Dave Schaumann) (03/18/91)
In article <65837@eerie.acsu.Buffalo.EDU> chu@acsu.buffalo.edu (john c chu) writes: |In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: |[concerning "if ( a = b )" |>Certainly it |>is a legal construction, but 90% of the time when I do this it |>was my mistake! | |It's been my mistake everytime I've done it!! I realize that it is a |legal construction and I know what it does, but I was wondering... |Is there a good use for this? How about: if( ptr = malloc(sizeof(spam)) ) { <stuff> } else panic( "Time to buy some more memory!" ) ; Now I realize that this is not the normal idiom for checking for a NULL malloc, but it does work, and has a certain charm in that the if-expression is rather simpler than the usual if( (ptr = malloc(sizeof(spam))) == NULL ) ...etc... -- Dave Schaumann | dave@cs.arizona.edu | Short .sig's rule!
ckp@grebyn.com (Checkpoint Technologies) (03/18/91)
In article <65837@eerie.acsu.Buffalo.EDU> chu@acsu.buffalo.edu (john c chu) writes: >In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: >[concerning "if ( a = b )" >>Certainly it >>is a legal construction, but 90% of the time when I do this it >>was my mistake! > >It's been my mistake everytime I've done it!! I realize that it is a >legal construction and I know what it does, but I was wondering... >Is there a good use for this? No. More specifically, as long as it's really a simple assignment with no side effects, it's out. You *can* do this, and some might say it's a "valid" use: b = function(args); if(a = b) { ... Some programmer might have really meant it this way, to test the result from the function call for zero. But if I were writing it (and I hazard to guess most everyone else reading this would agree, at least in principle) it would appear this way: a = b = function(args); if(a) { .. /* or else if(b) */ I have seen the following code examples frequently, and I consider them valid: if(code = setjmp(jmploc)) { ... - and - if(pid = fork()) { ... The reason they are valid is because the expression contains a significant side effect. -- First comes the logo: C H E C K P O I N T T E C H N O L O G I E S / / ckp@grebyn.com \\ / / Then, the disclaimer: All expressed opinions are, indeed, opinions. \ / o Now for the witty part: I'm pink, therefore, I'm spam! \/
eychaner@suncub.bbso.caltech.edu (Amateurgrammer) (03/18/91)
chu@acsu.buffalo.edu (john c chu) writes: >bill@camco.Celestial.COM (Bill Campbell) writes: >[concerning "if ( a = b )"] >>Certainly it is a legal construction, but 90% of the time when I do this it >>was my mistake! > >It's been my mistake everytime I've done it!! I realize that it is a >legal construction and I know what it does, but I was wondering... >Is there a good use for this? Sure. That's an easy one. Example: if (stat = some_func(...)) printf("Error %d: %s\n", stat, errstr(stat)); some_func(...) is a function which returns 0 if it completes successfully, and an error code processed to s string by errstr(stat) if it fails. I know this isn't the greatest code, but you get the idea (I hope...). ****************************************************************************** Glenn Eychaner - Big Bear Solar Observatory - eychaner@suncub.bbso.caltech.edu "Studies have shown that it is cheaper to build things that don't work than things that do." -Jeff Nenow, BBSO
drh@duke.cs.duke.edu (D. Richard Hipp) (03/18/91)
In article <65837@eerie.acsu.Buffalo.EDU> chu@acsu.buffalo.edu (john c chu) writes: >In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: >[concerning "if ( a = b )" >>Certainly it >>is a legal construction, but 90% of the time when I do this it >>was my mistake! > >It's been my mistake everytime I've done it!! I realize that it is a >legal construction and I know what it does, but I was wondering... >Is there a good use for this? Here is something I do a lot, to remove the "\n" from the end of a string (something that is commonly necessary if "fgets" is used to read lines): if( cp=strchr(buf,'\n') ) *cp = 0; Actually, I usually write this slightly different, to avoid complaints from lint about suspicious assignments used as booleans: if( (cp=strchr(buf,'\n'))!=0 ) *cp = 0; The same code gets generated either way.
darcy@druid.uucp (D'Arcy J.M. Cain) (03/18/91)
In article <65837@eerie.acsu.Buffalo.EDU> john c chu writes: >It's been my mistake everytime I've done it!! I realize that it is a >legal construction and I know what it does, but I was wondering... >Is there a good use for this? Certainly: if (a = b()) ...; Where the body uses the value returned from b(). For readability you could write: a = b(); if (a) ...; but that isn't very efficient. I prefer the following: if ((a = b()) != 0) ...; On any reasonable compiler that should generate the same code as the first example but my intention is perfectly clear. Anyone trying to maintain my code doesn't have to investigate the surrounding code when he sees that to figure out if I really meant it. -- D'Arcy J.M. Cain (darcy@druid) | D'Arcy Cain Consulting | There's no government Toronto, Ontario, Canada | like no government! +1 416 424 2871 |
grover@sonny-boy.cs.unlv.edu (Kevin Grover) (03/19/91)
In article <65837@eerie.acsu.Buffalo.EDU>, chu@acsu.buffalo.edu (john c chu) writes: ) From: chu@acsu.buffalo.edu (john c chu) ) Subject: When do you use "if ( a = b )"? (was Re: Funny mistake) ) Date: Sun, 17 Mar 91 04:53:11 PST ) Organization: SUNY Buffalo ) ) In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: ) [concerning "if ( a = b )" ) >Certainly it ) >is a legal construction, but 90% of the time when I do this it ) >was my mistake! ) ) It's been my mistake everytime I've done it!! I realize that it is a ) legal construction and I know what it does, but I was wondering... ) Is there a good use for this? ) There are plenty of uses for it. It will allow smaller code, and checks to be done quikcer. I have done it by mistake a time or two, but I find it quickly. One, of my most common uses is if ( !(fp=fopen("file","r")) ) perror ("Could not open file"); Which is the same (logically) as: if ( (fp=fopen("file","r")) == NULL ) perror ("Could not open file"); This code tries to open the file, if it did not, if prints a message (and aborts) the program. You could then put the rest of the code in an else (for clarity) or simply put it after the if. Also, if you get bitten but this bug often, try something like #define EQU == if ( a EQU b) Instead of depending upon remembering to use '==' when you need to. -- +-------------------------------------------------+----------------------+ | Kevin Grover UNLV Computer Science | Home of the | | grover@cs.unlv.edu Las Vegas, Nevada | Running REBELS | +-------------------------------------------------+----------------------+
michi@ptcburp.ptcbu.oz.au (Michael Henning) (03/19/91)
grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: [ Stuff deleted I entirely agree with ] >Also, if you get bitten but this bug often, try something like > #define EQU == > if ( a EQU b) >Instead of depending upon remembering to use '==' when you need to. NO, NO, NO ! Please don't do this. There is nothing worse than a set of macros that redefine the syntax of the language without achieving anything else. Have you ever seen the original source for the Bourne shell ? It is written with a set of macros that try to make it look like Algol. Almost impossible to understand. Similarly, #defines like #define or || #define and && #define not ! #define begin { #define end } contribute nothing to the readability of the code, but make it worse (IMHO). No matter who hard you try, C is not Pascal. #define EQU == falls into the same category. Granted, using = instead of == is a common mistake, and people do get bitten. If C had used := and == instead, the problem would not exist. Still, things are the way they are, and macros to "improve" the language won't help. Much better to get used to the deficiencies of C and to live with them. Simply say 1000 times: "I shalt never again use = instead of ==". And besides, are you going to change every occurrence of == to EQU in every piece of code you will ever maintain ? I don't think that you would make many friends that way, a lot of software maintenance relies on noise-free diff listings. Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
torek@elf.ee.lbl.gov (Chris Torek) (03/20/91)
In article <1991Mar18.195351.11985@unlv.edu> grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: >There are plenty of uses for it. It will allow smaller code, and checks to be >done quicker. Smaller source code, yes. Smaller or faster object code---well, if your compiler generates different code for if (a = b) than for a = b; if (a) then your compiler is not worth what you paid for it. (Well, with two possible exceptions: if you have turned off all optimization, or if `a' is declared `volatile'.) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
grover@lowell.cs.unlv.edu (Kevin Grover) (03/20/91)
michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: ) grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: ) ) [ Stuff deleted I entirely agree with ] ) ) >Also, if you get bitten but this bug often, try something like ) ) > #define EQU == ) ) > if ( a EQU b) ) ) >Instead of depending upon remembering to use '==' when you need to. ) ) NO, NO, NO ! Please don't do this. [ misc. flame deleted ...] ) And besides, are you going to change every occurrence of == to EQU in every ) piece of code you will ever maintain ? I don't think that you would make ) many friends that way, a lot of software maintenance relies on noise-free ) diff listings. Just so you know, I agree completely. I have never, and will never use such a construct. I merely thought if it on the fly, as a means to help those suffer from that problem ( using = in place of ==) get alone with as little difficulty as possible. However, I do not understand why you are so against such a use of define. I agree that it might be a pain on a continual basis, but any person who expects to use C regularly will (hopefully) discover this, and finally learns that using = in a test is very usefull, or possibly quite using C. -- +-------------------------------------------------+----------------------+ | Kevin Grover UNLV Computer Science | Home of the | | grover@cs.unlv.edu Las Vegas, Nevada | Running REBELS | +-------------------------------------------------+----------------------+
hagins@gamecock.rtp.dg.com (Jody Hagins) (03/20/91)
In article <65837@eerie.acsu.Buffalo.EDU>, chu@acsu.buffalo.edu (john c chu) writes: |> In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: |> [concerning "if ( a = b )" |> >Certainly it |> >is a legal construction, but 90% of the time when I do this it |> >was my mistake! |> |> It's been my mistake everytime I've done it!! I realize that it is a |> legal construction and I know what it does, but I was wondering... |> Is there a good use for this? Sure. Any time you want to test the result of an assignment. However, you might want to use this instead: if ((a = b) != 0) The compiler SHOULD generate the same code, but you do not get the headaches that can result from: if (a = b) |> |> john |> chu@autarch.acsu.buffalo.edu |> -- Jody Hagins hagins@gamecock.rtp.dg.com Data General Corp. 62 Alexander Dr. RTP, N.C. 27709 (919) 248-6035 Nothing I ever say reflects the opinions of DGC.
jeff@Ingres.COM (Jeff Anton) (03/20/91)
Consider: if (tmp = *wakeup_pid) { kill(tmp, SIGALRM); *wakeup_pid = 0; } wakeup_pid is in shared memory. Several programs may run this code segment at once. If it were written like: if (*wakeup_pid) { kill(*wakeup_pid, SIGALRM); *wakeup_pid = 0; } Then there is a race condition where the loser process might call kill(0, SIGALRM) which will be very nasty as it kills the current process group. Of course you could write this like: tmp = *wakeup_pid; if (tmp) { kill(tmp, SIGALRM); *wakeup_pid = 0; } But the separation of the assignment and the if invites new code between the two which will increase the likelyhood of race conditions. There is no side effect in the assignment in the if in this case unless you consider any shared memory access to have side effects. Jeff Anton (p.s. Semaphores would be a safer way to deal with this) (p.p.s. All such code which has such complex behavior but reads simply should have a comment describing the complexities)
jlg@cochiti.lanl.gov (Jim Giles) (03/20/91)
In article <11109@dog.ee.lbl.gov>, torek@elf.ee.lbl.gov (Chris Torek) writes: |> [...] |> Smaller source code, yes. Smaller or faster object code---well, if |> your compiler generates different code for |> |> if (a = b) |> |> than for |> |> a = b; |> if (a) |> |> then your compiler is not worth what you paid for it. [...] Even if it was _free_! The above 'optimization' was present in Fortran compilers more than 30 years ago - and their _fastest_ machines were slow compared to today's micros (so the excuse that doing the above analysis makes the compiler too slow or complex is garbage). J. Giles
eric@cinnet.com (Eric Bardes) (03/20/91)
A typical usage, though slightly more hidden, of ( a = b ) in a conditional expression would be this: char *a, *b; while (*a++ = *b++) /* empty */ ; This example copies from string b to string a include the null character. Note the while loop has no body. Eric
al@unhd.unh.edu (Anthony Lapadula) (03/20/91)
In article <357@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: > >Simply say 1000 times: > > "I shalt never again use = instead of ==". The way I remember this is simple. I've made a mental note that "==" is two characters long, as are "<=" and ">=". When I read code to myself, these latter two come out as "less than or equal" and "greater than or equal"; "==" comes out as "equal equal." Heck, maybe it only works for me. :-) -- Anthony (uunet!unhd!al, al@cs.unh.edu) Lapadula
bhoughto@hopi.intel.com (Blair P. Houghton) (03/20/91)
In article <1991Mar19.192416.13756@unlv.edu> grover@lowell.cs.unlv.edu (Kevin Grover) writes: >michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >>grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: >>> >>> #define EQU == >>> if ( a EQU b) >> >>NO, NO, NO ! Please don't do this. >>And besides, are you going to change every occurrence of == to EQU in every > >[...]I do not understand why you are so against such a >use of define. I agree that it might be a pain on a >continual basis, but any person who expects to use C >regularly will (hopefully) discover this, and finally >learns that using = in a test is very usefull, or possibly >quite using C. [sic] #define should _never_ be used to replace existing tokens. Doing so constitutes a very effective obfuscation. Check the 1990 winners of the International Obfuscated C Code Contest; you won't find a single one that doesn't use #define to thoroughly encrypt the code). #define has many uses in the vein of anti-obfuscation. E.g.: creating lexical abbreviations for complex inventions; localizing the definition of a widely-used constant; and, giving mnemonic significance to an otherwise anonymous token (like, `#define BOHR_MAGNETON (9.27e-24)'). What "any person who expects to use C learns" is that `=' and `==' are (very) likely to be interchanged, and it's wise to make a pass through your code just to look for those spots, when debugging indicates that bad values may be causing improper flow of control. --Blair "But what else is a debugger for?" P.S. Emacs obviates the desire to `#define BEGIN {' and `#define END }', by automatically indicating matching braces (although your style should do that itself), but has anyone made it check or warn that you're using `=' and `==' in an uncommon way?
av@kielo.uta.fi (Arto V. Viitanen) (03/20/91)
>>>>> On 19 Mar 91 19:13:45 GMT, torek@elf.ee.lbl.gov (Chris Torek) said:
Chris> X-Local-Date: Tue, 19 Mar 91 11:13:46 PST
Chris> In article <1991Mar18.195351.11985@unlv.edu> grover@sonny-boy.cs.unlv.edu
Chirs> ---well, if
Chris> your compiler generates different code for
Chris> if (a = b)
Chris> than for
Chris> a = b;
Chris> if (a)
Chris> then your compiler is not worth what you paid for it.
I checked those differences with SUN's cc (SUN3/SunOs 4.0.3) and GNU cc
(version 1.39) In SUN's cc there was differences when optimization was turned
off; they generated same assembler code whith optimization. In GNU cc, it was
other way round: without optimization, assembler code was same, but with
optimization, they were different.
I think GNU cc is still worth it price !!
Chris> In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Chris> Berkeley, CA Domain: torek@ee.lbl.gov
--
Arto V. Viitanen email: av@kielo.uta.fi
University Of Tampere, av@ohdake.cs.uta.fi
Finland
ttobler@unislc.uucp (Trent Tobler) (03/21/91)
From article <65837@eerie.acsu.Buffalo.EDU>, by chu@acsu.buffalo.edu (john c chu): > In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: > [concerning "if ( a = b )" >>Certainly it >>is a legal construction, but 90% of the time when I do this it >>was my mistake! > > It's been my mistake everytime I've done it!! I realize that it is a > legal construction and I know what it does, but I was wondering... > Is there a good use for this? Yes. I often use it to do the following... --------------------- if( fp = fopen( fname, "r")) { do_stuff_to(fp); fclose(fp); } else perror( fname); ---------------------- Of course, it could be written with fp = fopen ... on a line by itself, followed by an if(fp) ... , but I find the above easier to follow. -- Trent Tobler - ttobler@csulx.weber.edu , ttobler@unislc!sun!uucp
mercer@npdiss1.StPaul.NCR.COM (Dan Mercer) (03/21/91)
In article <1991Mar19.223605.24858@unhd.unh.edu> al@unhd.unh.edu (Anthony Lapadula) writes: :In article <357@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: :>grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: :> :>Simply say 1000 times: :> :> "I shalt never again use = instead of ==". : :The way I remember this is simple. I've made a mental note that "==" :is two characters long, as are "<=" and ">=". When I read code to myself, :these latter two come out as "less than or equal" and "greater than or :equal"; "==" comes out as "equal equal." : :Heck, maybe it only works for me. :-) : :-- Anthony (uunet!unhd!al, al@cs.unh.edu) Lapadula Works for me too. Actually, when I was just learning I went farther than that, to defining macros for == <> != (!= was actually the most difficult for me, because I programmed in several other languages where ^= was not equals. This causes some very starnge bugs in C). This was ugly, but got me through my first couple of projects. By then, I was so used to typing EQ for ==, that I made EQ an abbreviation for == in vi. Now vi handles the problem for me. -- Dan Mercer NCR Network Products Division - Network Integration Services Reply-To: mercer@npdiss1.StPaul.NCR.COM (Dan Mercer) "MAN - the ultimate one word oxymoron in the English Language"
torek@elf.ee.lbl.gov (Chris Torek) (03/21/91)
In article <AV.91Mar20084724@kielo.uta.fi> av@uta.fi (Arto Viitanen) writes: [gcc version 1.39 on Sun-3, compiling `if (a = b)' vs `a = b; if (a)'] >In GNU cc, it was other way round: without optimization, assembler code >was same, but with optimization, they were different. That is peculiar. I tried the same thing, with the same gcc, on the same machine, and got identical code when optimized, different (poorer) code for the second when not, exactly as expected. (gcc without -O typically produces truly awful code: the compiler relies quite heavily on optimization to clean up after the initial code generation. This is reasonable, but does mean that you probably never should compile without -O unless you are trying to debug the compiler itself.) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
Sepp@ppcger.ppc.sub.org (Josef Wolf) (03/21/91)
torek@elf.ee.lbl.gov (Chris Torek) writes: ] Smaller source code, yes. Smaller or faster object code---well, if ] your compiler generates different code for ] if (a = b) ] than for ] a = b; ] if (a) ] then your compiler is not worth what you paid for it. You might be right in this point of view, but... Do you want the compiler to do your work? Do you think your employer would be happy? (ok, just joking ;-) Now let me comment your code: The upper code tends to be more clearly (_my_ opinion). If you got into that trap once or twice, you won't ever forget this problem. I've done this error _one_ time (well, we're not at the end of time ;-). It took about a week to find the bug. But now I'm pretty sure, I've never done _THAT_ sort of bug since these times... And now I like this sort of assignments because they are a.) short b.) clear (there are no unnecessary types around it to confuse you) The other problem is: if you change the name of expression 'a', you need to make some more changes -> you will get more chances to produce _new_ bugs. Well, the above is _my_ opinion. You have to find _your_ way to get around this problem. Greetings Sepp PS: I also got trapped into the foo (bar (a1, ..., aN), aN+1); versus foo (bar (a1, ..., aN, aN+1)); problem. And I'm pretty sure, I won't get into _that_ trap next years :-) | Josef Wolf, Germersheim, Germany | +49 7274 8047 -24 Hours- (call me :-) | ...!ira.uka.de!smurf!ppcger!sepp | +49 7274 8048 -24 Hours- | sepp@ppcger.ppc.sub.org | +49 7274 8967 18:00-8:00, Sa + Su 24h | "is there anybody out there?" | all lines 300/1200/2400 bps 8n1
rob@matterhorn.eng.ohio-state.edu (Rob Carriere) (03/22/91)
In article <11109@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes: >then your compiler is not worth what you paid for it. (Well, with two >possible exceptions: if you have turned off all optimization, or if `a' >is declared `volatile'.) Three: if the cost of the compiler was sufficiently negative. SR ---
d9erikb@dtek.chalmers.se (Erik Bergersjo) (03/22/91)
In article <65837@eerie.acsu.Buffalo.EDU> chu@acsu.buffalo.edu (john c chu) writes: >[concerning "if ( a = b )" > >Is there a good use for this? There sure is. I can think of two major uses: (I) b is a function, perhaps returning a pointer to something on success and NULL otherwise. (II) b is a hardware register, cleared on reading. Of course, in both cases "a = b; if( a )..." would do, but if you don't have a good optimizing compiler the final code might get worse. Besides, I think "if(a = b)" is more readable. It's clearly one of those extra features / pecularities that make C the special language it is! =============================================================================== Chalmers University | . . | "A message worth of Technology | Real life: Erik Bergersj o | spreading is Sweden | E-mail: d9erikb@dtek.chalmers.se | worth reading" ===============================================================================
torek@elf.ee.lbl.gov (Chris Torek) (03/22/91)
[I wrote: `if your compiler generates different code for embedded assignments than for separate assignments, that compiler is not worth what you paid for it.'] In article <dxj+VD@ppcger.ppc.sub.org> Sepp@ppcger.ppc.sub.org (Josef Wolf) writes: >You might be right in this point of view, but... [and goes on to argue that embedded assignment tends to be clearer.] I happen to agree---most often, a loop like: while ((c = getchar()) != EOF) { do some work; } is MUCH better, stylistically, than c = getchar(); while (c != EOF) { do some work; c = getchar(); } (Never mind translating into `for' loop syntax :-) ) >Well, the above is _my_ opinion. You have to find _your_ way to get >around this problem. Do not make the mistake of thinking that every argument I make is a direct clue to my own opinions. I could, for instance, show how VMS is better than <pick some version here> Unix at some particular task. (Such tasks do exist, especially with older Unixes.) Nonetheless, I have managed to avoid VMS systems for many years now, and plan to continue avoiding them. In this particular case, I would be quite happy with a compiler that warns about if (a = expr) ... but not about if ((a = expr) != 0) ... and I tend to write the latter when I mean `assign, then test the result'. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
av@kielo.uta.fi (Arto V. Viitanen) (03/22/91)
>>>>> On 20 Mar 91 21:45:46 GMT, torek@elf.ee.lbl.gov (Chris Torek) said: Chris> X-Local-Date: Wed, 20 Mar 91 13:45:47 PST Chris> In article <AV.91Mar20084724@kielo.uta.fi> av@uta.fi (Arto Viitanen) writes: Chris> [gcc version 1.39 on Sun-3, compiling `if (a = b)' vs `a = b; if (a)'] >In GNU cc, it was other way round: without optimization, assembler code >was same, but with optimization, they were different. Chris> That is peculiar. I tried the same thing, with the same gcc, on the Chris> same machine, and got identical code when optimized, different (poorer) Chris> code for the second when not, exactly as expected. Yes, you are right. I mixed somewhere result assembler codes; actually both SUN's and GNU's generate different codes without optimization and similar with optimization. What is more interesting, is the difference between codes of SUN and GNU: when C program is: #include <stdio.h> main () { int a,b; a = 1; if(a=b) printf("yes\n"); } , SUN's C compiler (SUN 3, SunOS 4.0.3) generates .data .text LL0: .proc |#PROC# 04 .data1 L29: .ascii "yes\012\0" LF25 = 8 LS25 = 0 LFF25 = 8 LSS25 = 0 LV25 = 8 .data .text .globl _main _main: |#PROLOGUE# 0 link a6,#-8 |#PROLOGUE# 1 moveq #1,d1 movl d1,a6@(-4) movl a6@(-8),a6@(-4) jeq L27 pea L29 jbsr _printf addqw #4,sp L27: moveq #0,d0 |#PROLOGUE# 2 unlk a6 |#PROLOGUE# 3 rts but gcc (version 1.39) generates #NO_APP gcc_compiled.: .text LC0: .ascii "yes\12\0" .even .globl _main _main: link a6,#0 tstl d0 jeq L2 pea LC0 jbsr _printf L2: unlk a6 rts It seems than GCC drops the whole test away !! -- Arto V. Viitanen email: av@kielo.uta.fi University Of Tampere, av@ohdake.cs.uta.fi Finland
hagins@gamecock.rtp.dg.com (Jody Hagins) (03/23/91)
In article <11309@dog.ee.lbl.gov>, torek@elf.ee.lbl.gov (Chris Torek) writes: |> [I wrote: `if your compiler generates different code for embedded |> assignments than for separate assignments, that compiler is not worth |> what you paid for it.'] |> |> In article <dxj+VD@ppcger.ppc.sub.org> Sepp@ppcger.ppc.sub.org (Josef Wolf) |> writes: |> >You might be right in this point of view, but... |> [and goes on to argue that embedded assignment tends to be clearer.] |> |> I happen to agree---most often, a loop like: |> |> while ((c = getchar()) != EOF) { |> do some work; |> } |> |> is MUCH better, stylistically, than |> |> c = getchar(); |> while (c != EOF) { |> do some work; |> c = getchar(); |> } |> |> (Never mind translating into `for' loop syntax :-) ) |> |> >Well, the above is _my_ opinion. You have to find _your_ way to get |> >around this problem. |> |> Do not make the mistake of thinking that every argument I make is a |> direct clue to my own opinions. I could, for instance, show how VMS |> is better than <pick some version here> Unix at some particular task. |> (Such tasks do exist, especially with older Unixes.) Nonetheless, I |> have managed to avoid VMS systems for many years now, and plan to |> continue avoiding them. |> |> In this particular case, I would be quite happy with a compiler that |> warns about |> |> if (a = expr) ... |> |> but not about |> |> if ((a = expr) != 0) ... That's exactly what Borland's C compilers do. |> |> and I tend to write the latter when I mean `assign, then test the result'. |> -- |> In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) |> Berkeley, CA Domain: torek@ee.lbl.gov |> -- Jody Hagins hagins@gamecock.rtp.dg.com Data General Corp. 62 Alexander Dr. RTP, N.C. 27709 (919) 248-6035 Nothing I ever say reflects the opinions of DGC.
mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/23/91)
In article <18401@lanl.gov>, jlg@cochiti.lanl.gov (Jim Giles) writes: > In article <11109@dog.ee.lbl.gov>, torek@elf.ee.lbl.gov (Chris Torek) writes: >> [I]f your compiler generates different code for >> if (a = b) >> than for >> a = b; if (a) >> then your compiler is not worth what you paid for it. [...] (I will assume you meant to say "better" instead of simply "different". On a SPARC, for example, there are at least three ways of implementing a test-for-zero, none of which is significantly better or worse than any other....) > Even if it was _free_! The above 'optimization' was present in > Fortran compilers more than 30 years ago - and [...]. Comparing FORTRAN optimizers to C optimizers is generally comparing apples and oranges. FORTRAN contains restrictions on the programmer that allow the optimizer vastly more latitude. Not that it's really got much to do with this case. If `a' has no side-effects (being a volatile variable counts as having side-effects), you both are quite right: there is no excuse for it. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
mike@sojurn.UUCP (Mike Sangrey) (03/25/91)
>) In article <775@camco.Celestial.COM> bill@camco.Celestial.COM (Bill Campbell) writes: >) [concerning "if ( a = b )" >) >) [Deleted ...] >) >) It's been my mistake everytime I've done it!! As an aside: you should get into the habit of putting the constant and function calls on the left of '=='. That way when you mess up with a '=' the compiler will 'Bzzzzzt'. The major problem with this idea is it looks funny. Of course, if we all did it this way ... ;-) mike ---------- "It muddles me rather." Pooh with apologies to A. A. Milne
conor@lion.inmos.co.uk (Conor O'Neill) (03/25/91)
To me it is clear that using assignments inside conditions is very bad
style because it makes the intention of the original programmer unclear.
The only sort of situation which I can think of where I _might_ consider
using it is something like the following:
if ( (x != 0) && ((a = expensive_function(x)) != 0) )
{
... do something involving 'a'
}
else if ... more complicated tests
This example cannot simply move the assignment to 'a' _out of_ the 'if',
because it is conditional on another condition, which may in itself be
complicated. The assignment cannot be moved _into_ the 'if', because
that would change the behaviour of the 'else' clauses.
Of course, there are a multiplicity of ways in which this small example
can be re-written so that the assignment is not inside the condition,
and most of them are probably clearer to read. I would use an alternative.
PS - The INMOS ANSI C compiler produces identical code for the following,
and warns about one of them:
lion/test(48)% cat -n c.c
1 int main(void)
2 {
3 int a, b ;
4 a = b;
5 if (a) b = 99;
6 a = b;
7 if (a != 0) b = 99;
8 if (a = b) b = 99; /* This is the confusing one */
9 if ((a = b) != 0) b = 99;
10 return 99;
11 }
lion/test(49)% icc c.c
Warning-icc-c.c(8)- use of '=' in condition context
lion/test(50)%
This warning can be suppressed by a command line switch.
---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".
darren@revcan.UUCP (Darren Morbey) (03/25/91)
In article <3130@inews.intel.com>, bhoughto@hopi.intel.com (Blair P. Houghton) writes: >In article <1991Mar19.192416.13756@unlv.edu> grover@lowell.cs.unlv.edu (Kevin Grover) writes: >>michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >>>grover@sonny-boy.cs.unlv.edu (Kevin Grover) writes: >>>> #define EQU == >>>> if ( a EQU b) >>>NO, NO, NO ! Please don't do this. >#define should _never_ be used to replace existing tokens. Just as a suggestion, what about: #define EQU(l,r) ((l)==(r)) /*...*/ if( EQU(a,b) ) I realize this is rather messy, because it "contribute[s] nothing to the readability of the code." (Mr. Henning) It does make the equality different from the assignment without violating "#define should _never_ be used to replace existing tokens." (Mr. Houghton) Pardon me for asking, but please define "obfuscation." P.S. I would find it useful to #define NOT(a) !(a), #define COMPL(a) ~(a), and #define XOR(a,b) ((a)^(b)). I have trouble remembering the use of the tilde and circumflex. Again, only a suggestion.
darren@revcan.UUCP (Darren Morbey) (03/25/91)
In article <150@revcan.UUCP>, my .signature didn't come through.
Here it is (sorry about that)...
darren@revcan.UUCP (Darren Morbey) (03/25/91)
In article <153@revcan.UUCP>, darren@revcan.UUCP (Darren Morbey) writes: > In article <150@revcan.UUCP>, my .signature didn't come through. > Here it is (sorry about that)... It still didn't. I'll just put it in manually... [[ Darren Morby +1 613 957 9281 {uunet|lsuc|fts1}!revcan!darren ]] [[ Revenue Canada Taxation, 3052-400 Cumberland St, Ottawa,ON K1A 0L8 ]]
richard@aiai.ed.ac.uk (Richard Tobin) (03/27/91)
In article <1991Mar21.213027.24314@mathrt0.math.chalmers.se> d9erikb@dtek.chalmers.se (Erik Bergersjo) writes: >Besides, I think "if(a = b)" is more readable. It's clearly one of those >extra features / pecularities that make C the special language it is! It's hardly a peculiarity of C. It's just part of C's rather limited attempt to be an expression language. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
gwyn@smoke.brl.mil (Doug Gwyn) (03/27/91)
In article <15053@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes: >To me it is clear that using assignments inside conditions is very bad >style because it makes the intention of the original programmer unclear. I think it depends on context and familiraity with common C idioms. Consider while ( (c = getchar()) != EOF ) ... I know of no clearer expression of this common operation.
michi@ptcburp.ptcbu.oz.au (Michael Henning) (03/27/91)
darren@revcan.UUCP (Darren Morbey) writes: >Just as a suggestion, what about: > #define EQU(l,r) ((l)==(r)) /*...*/ if( EQU(a,b) ) >I realize this is rather messy, because it >"contribute[s] nothing to the readability of the code." (Mr. Henning) >It does make the equality different from the assignment without violating >"#define should _never_ be used to replace existing tokens." (Mr. Houghton) If you realize that it is rather messy, why do it ? When someone else, who is not familiar with your coding style, gets to see this, he most likely won't know immediately what EQU means, and he will have to go hunting for the macro definition (not always easy if there are a lot of source and header files). What is the point of taking an operator that is already defined in the language and making it look like something else ? >Pardon me for asking, but please define "obfuscation." Your EQU *is* obfuscation, because it replaces something that everyone knows about and can understand (==) with something that no one knows about (EQU). >P.S. I would find it useful to #define NOT(a) !(a), > #define COMPL(a) ~(a), and #define XOR(a,b) ((a)^(b)). > I have trouble remembering the use of the tilde and > circumflex. Again, only a suggestion. If you have trouble remembering !, ~ and ^, then learn them, don't #define them to something else that *you* find easier, but many other people will only find annoying. Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
bhoughto@hopi.intel.com (Blair P. Houghton) (03/27/91)
In article <15053@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes: >To me it is clear that using assignments inside conditions is very bad >style because it makes the intention of the original programmer unclear. No, it's bad because it's an unnecessary obfuscation. No compiler in the world won't make a=b if(a) the same as if(a=b) as far as any user can tell (provided codocil 4 of para 16 of the charter of the League of Nations is followed and you didn't declare a as volatile or apply the -g flag...) >The only sort of situation which I can think of where I _might_ consider >using it is something like the following: > >if ( (x != 0) && ((a = expensive_function(x)) != 0) ) > { > ... do something involving 'a' > } >else if ... more complicated tests Well, the one I always fret over is if ( rindex(path,'/') ) /* dammit; another pathname */ strcat(newpath, 1+rindex(path,'/')); else /* bitchin'; just a filename */ strcat(newpath, path); Yeah, I can declare another variable, but golly, bytes are soooo expensive... (No strrchr-flames, please; I don't do this where I have an ANSI library). > 5 if (a) b = 99; > 7 if (a != 0) b = 99; > 8 if (a = b) b = 99; /* This is the confusing one */ > 9 if ((a = b) != 0) b = 99; >lion/test(49)% icc c.c >Warning-icc-c.c(8)- use of '=' in condition context >lion/test(50)% Nice stuff. Did you try if ( (a==b) != 0 ) and get a redundancy error? --Blair "Some of us are redundant. Others merely overloaded."
dmm@cfa.harvard.edu (David Meleedy) (03/28/91)
I would like to respond to the view that statements such as
#define EQU ==
are to be avoided.
I disagree entirely. One of the well known conventions in C is that anything
in all capital letters is defined in a define statement. It is the
responsibility of the programmer to know to look up and see what various
defines are. If the defined words are chosen well, this may even be
unnecessary. The time it takes to debug a program that has 1 equal instead of
2 in an if statement does not justify the minisule effort required to understand
that EQU is equivalent to ==. I have seen C code written with many defines
that looks just like pascal. I do not criticize or condone this type of
programming because it is not hard to make sense out of structured and well
thought out defines. You should not limit yourself to understanding *only* the
look of C code. Any well structured looking algorithm should be apparent in
what it does.
if (a EQU b) {
...
}
is perfectly reasonable... in fact here is an example of some pascal type
code in c:
#include <math.h>
#define REAL float
#define BEGIN {
#define WHILE while(
#define DO )
#define END ;}
#define WRITELN(x) printf("%s\n",x)
#define READ(x) scanf("%f",&x)
#define IF if(
#define THEN )
#define ELSE ;else
#define GETS =
#define EQUALS ==
#define NOT !
#define WRITE(x) printf(" %f ", x)
#define PROGRAM main()
PROGRAM
BEGIN
REAL a,b,c,root1,root2,discriminant;
a GETS 1 ;
WHILE NOT ( a EQUALS 0 ) DO
BEGIN
WRITELN(" Quadratic Equation Solver. What are a,b, and c? ");
WRITELN(" Enter 0 alone to exit program.");
READ( a );
IF NOT( a EQUALS 0 ) THEN
BEGIN
READ( b ) ; READ( c );
IF b * b - 4 * a * c < 0 THEN
WRITELN(" No Real Roots ")
ELSE
BEGIN
discriminant GETS b * b - 4*a*c ;
root1 GETS ( -b + sqrt( discriminant ) )/ 2*a ;
root2 GETS ( -b - sqrt( discriminant ) )/ 2*a ;
WRITELN(" The roots are ");
WRITE(root1) ; WRITE(root2) ; WRITELN("")
END
END
END
END
admittedly it's not perfect pascal, but it is certainly readable and
understandable.
_David Meleedy
michi@ptcburp.ptcbu.oz.au (Michael Henning) (03/28/91)
dmm@cfa.harvard.edu (David Meleedy) writes: >is perfectly reasonable... in fact here is an example of some pascal type >code in c: >#include <math.h> >#define REAL float >#define BEGIN { >#define WHILE while( [ More stuff deleted ] >#define PROGRAM main() >PROGRAM >BEGIN > REAL a,b,c,root1,root2,discriminant; > a GETS 1 ; > WHILE NOT ( a EQUALS 0 ) DO > BEGIN > WRITELN(" Quadratic Equation Solver. What are a,b, and c? "); > WRITELN(" Enter 0 alone to exit program."); > READ( a ); [ More stuff deleted ] >admittedly it's not perfect pascal, but it is certainly readable and >understandable. Most places I've worked for, writing code like that would have cost me my job. Are you really serious about this ? Are you really suggesting that this is an improvement over writing the same thing without macros ? Why don't you write it in Pascal in the first place if you want it to look like it ? Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
steve@taumet.com (Stephen Clamage) (03/28/91)
dmm@cfa.harvard.edu (David Meleedy) writes: >I would like to respond to the view that statements such as >#define EQU == >are to be avoided. >I disagree entirely. One of the well known conventions in C is that anything >in all capital letters is defined in a define statement. It is the >responsibility of the programmer to know to look up and see what various >defines are. This is a limited view, IMHO. Here is an example from an actual program: int i AND j; You could sort of see what the programmer had in mind -- except that && would be illegal in this context, so maybe 'int i, j;' was intended. It turned out that the program had the line #define AND ; long so the code really meant int i; long j; How many include files had to be scanned to find this abomination? Once you start using macros for standard language constructs, where do you stop? #define BEGIN { #define END { #define AND && #define OR || #define IF if #define THEN { #define ELSE } else { #define ELSEIF } else if #define ENDIF } Some would claim that this set of defines makes for a much more readable program. It is not easier for experienced C programmers who have to look up and mentally translate these constructs into standard C. The original programmer may have found a set of unusual macros convenient after becoming accustomed to programming with them, but what about those who come later and have to maintain the code? Finally, there are a lot of tools which do simple syntax scans of programs to provide various analyses of the code. What makes these convenient is that they can scan files without having to do a full preprocessor pass first. If you subvert the standard syntax of C, these tools become less convenient or impossible to use. -- Steve Clamage, TauMetric Corp, steve@taumet.com
gwyn@smoke.brl.mil (Doug Gwyn) (03/29/91)
In article <1991Mar28.004147.705@worf.harvard.edu> dmm@cfa.harvard.edu (David Meleedy) writes: >I would like to respond to the view that statements such as >#define EQU == >are to be avoided. >I disagree entirely. You are entitled to your opinion, but I should point out that such use of the preprocessor was used by Steve Bourne in the source code for the Bourne shell (/bin/sh) and the "adb" debugger on UNIX, in order to make the code look more like Algol (just as in your example), and programmers that had to maintain that code almost invariably cursed Bourne for doing that. Eventually, the Bourne shell source was de-Algolized (by Dave Korn, if I recall correctly), so the version that AT&T now distributes (and that I for one maintain for BRL) is now in ordinary C. Even though I had gotten accustomed to the Algolized version, I like the patent C version much better; I have only ONE programming language to conceptually deal with, not TWO.
stanley@phoenix.com (John Stanley) (03/29/91)
gwyn@smoke.brl.mil (Doug Gwyn) writes: > cursed Bourne for doing that. Eventually, the Bourne shell source > was de-Algolized (by Dave Korn, if I recall correctly), so the version You mean he, like, ran it through the preprocessor and, sorta, let the preprocessor convert all the Algol to the real C?
ark@alice.att.com (Andrew Koenig) (03/29/91)
In article <3482@inews.intel.com> bhoughto@hopi.intel.com (Blair P. Houghton) writes: > No compiler > in the world won't make > a=b > if(a) > the same as > if(a=b) > as far as any user can tell A while ago I remember a big argument about the difference between code generated by a particular compiler for this: a=b-c; if(a) and for this if(a=b-c) In the first case, the compiler dutifully stored b-c in a and then tested the value of a. In the second, it generated a three-address subtract instruction to put the result in a and then did a conditional jump based on the condition code resulting from the subtract. You'd think those would have the same effects, wouldn't you? It turned out that the effects differed if the subtract caused an overflow (call it underflow if you like) with a zero result. In the first case, the test would show that a==0. In the second, the condition code would show an overflow. Overflow is not the same as zero, so the test would fail. I believe that this behavior on the part of the compiler is entirely reasonable. -- --Andrew Koenig ark@europa.att.com
dmm@cfa.harvard.edu (David Meleedy) (03/30/91)
If someone is having a lot of trouble because (s)he is using an assignment instead of a test for equality, then I still have no problem with person using the: #define EQU == in fact, if it really gets under your skin, you can take the source code, use a good editor to replace every EQU string with ==, and then delete the define statement at the top. In fact you could do that will all but the pseudo-macros like WRITE(x) in the Pascal example that I sent in. So I guess the arguments that it's too hard to translate for an experienced C programmer don't hold any water for me, because an experienced C programmer knows how to use an editor and replace strings that bother him/her. -David Meleedy dmm@worf.harvard.edu
gwyn@smoke.brl.mil (Doug Gwyn) (03/30/91)
In article <866JZ5w163w@phoenix.com> stanley@phoenix.com (John Stanley) writes: >> cursed Bourne for doing that. Eventually, the Bourne shell source >> was de-Algolized (by Dave Korn, if I recall correctly), so the version > You mean he, like, ran it through the preprocessor and, sorta, let >the preprocessor convert all the Algol to the real C? No, if you think about it you should see that preprocessing it via cpp would not have been desirable. I don't know exactly how he did it, but one possibility would have been to temporarily disable the # directives, except for the ones that #defined the Algolish macros, and preprocess just that, the reenable the remaining # directives. The way cpp works, probably some additional cleanup would have been necessary afterwards.
wirzenius@cc.helsinki.fi (Lars Wirzenius) (03/30/91)
In article <1991Mar29.195622.321@worf.harvard.edu>, dmm@cfa.harvard.edu (David Meleedy) writes: > in fact, if it really gets under your skin, you can take the source code, > use a good editor to replace every EQU string with ==, and then delete the > define statement at the top. In fact you could do that will all but the Of course you could, except if might not work, as EQU might mean something else inside a string, for instance. You can't even use the preprocessor, since that would expand everything else as well. The major point is, why should you have to? Using define to change the syntax essentially creates a new language, which forces everyone to learn it. It is much better for the original programmer to learn to type better, or to use code templates or an abbreviation expanding editor. -- Lars Wirzenius wirzenius@cc.helsinki.fi
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/01/91)
In article <1991Mar30.155003.5775@cc.helsinki.fi> wirzenius@cc.helsinki.fi (Lars Wirzenius) writes: > The major point is, why should you have to? Using define to change the > syntax essentially creates a new language, which forces everyone to > learn it. On the other hand, #define equ(a,b) ((a) == (b)) does not create a new syntax or a new language---but it's still an extra semantic burden for the reader. In fact, *anything* that extends the global namespace makes the code more difficult to read. That's why you shouldn't even define a function unless it encapsulates nontrivial semantic content. ---Dan
markh@csd4.csd.uwm.edu (Mark William Hopkins) (04/01/91)
In article <1991Mar29.195622.321@worf.harvard.edu>, dmm@cfa.harvard.edu (David Meleedy) writes: > in fact, if it really gets under your skin, you can take the source code, > use a good editor to replace every EQU string with ==, and then delete the > define statement at the top. In fact you could do that will all but the In article <1991Mar30.155003.5775@cc.helsinki.fi> wirzenius@cc.helsinki.fi (Lars Wirzenius) writes: >Of course you could, except if might not work, as EQU might mean >something else inside a string, for instance. You can't even use the >preprocessor, since that would expand everything else as well. Come on people. You're discussing a non-essential problem. If you don't like somebody else's macros, then just filter it out with the macro preprocessor on your system. If you don't have one write it yourself. Scanners and preprocessors are trivial to write. I use my own scanner-based program to alter variable names and macros in other peoples' source all the time. It's nothing.
markh@csd4.csd.uwm.edu (Mark William Hopkins) (04/01/91)
In article <15053@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes: >To me it is clear that using assignments inside conditions is very bad >style because it makes the intention of the original programmer unclear. Then render this in a suitable format that avoids needless redundancy: if ((A = f1()) != 2 || (A = f2()) != 3 || (A = f3()) != 4) f4(A); else Error(A); I believe that your proposed definition of clarity would be turned on its head with this example. Mixing imperatives with expressions accords well with the style of natural language (as opposed to a purely logical style), and thus can read better. This especially goes for the logical operators, which actually translate better as natural language connectives (with all its temporal connotations) than pure logic connectives (e.g. and = and then). Witness this classic (I saw something like it in YACC source): (A = new-object()) || Error(A); Translation: "Make a new object or bust." Or... (Op = FindOp(S)) && return Op->Type || (Sym = NewSym(S)) && return Sym->Index; Translation: "Find an operator to match the string S and return its type, or make a symbol to match S and return its index."
byron@archone.tamu.edu (Byron Rakitzis) (04/01/91)
In article <10655@uwm.edu> markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: > >if ((A = f1()) != 2 || (A = f2()) != 3 || (A = f3()) != 4) [etc.] >I believe that your proposed definition of clarity would be turned on its head >with this example. I don't know whose definition of clarity you were referring to, but I don't think any of the "anti-assignment-in-if-statement" people can object with the above line. Note that the above line does *not* read: if (!(A = f1() - 2 && A = f2() - 3 && A = f3() - 4)) ... which I consider to be in the Canonical Obfuscated Form. >Mixing imperatives with expressions accords well with the style of natural >language (as opposed to a purely logical style), and thus can read better. Fair enough. No one (as far as I know) has objected to this style as long as the programmer's intent is unambiguous. >This especially goes for the logical operators, which actually translate >better as natural language connectives (with all its temporal connotations) >than pure logic connectives (e.g. and = and then). >Witness this classic (I saw something like it in YACC source): > (A = new-object()) || Error(A); >Translation: "Make a new object or bust." This style of "hack" actually comes from UNIX shells, where the || and && have precisely those semantics. However, in C you might run afoul because the datatype of "new-object()" and "Error()" are (might be) different. Some compilers object to this. >Or... (Op = FindOp(S)) && return Op->Type || > (Sym = NewSym(S)) && return Sym->Index; Same deal. In fact, I seriously doubt that this is legal C at all, since "return foo" is not an expression in C; it's a control statement. If I *had* to code the above using a single statement, I'd do it so: return ((Op = FindOp(S)) != NULL) ? Op->Type : (((Sym = NewSym(S)) != NULL) ? Sym->Index : NULL); but I'd much *rather* type if ((Op = FindOp(s)) != NULL) return Op->Type; else if ((Sym = NewSym(s)) != NULL) return Sym->Index; else return NULL;
byron@archone.tamu.edu (Byron Rakitzis) (04/01/91)
In article <13980@helios.TAMU.EDU> byron@archone.tamu.edu (Byron Rakitzis) writes: >In article <10655@uwm.edu> markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: >>if ((A = f1()) != 2 || (A = f2()) != 3 || (A = f3()) != 4) > [etc.] >Note that the above line does *not* read: > if (!(A = f1() - 2 && A = f2() - 3 && A = f3() - 4)) >which I consider to be in the Canonical Obfuscated Form. In my anxiousness to convert the first statement to C.O.F., I erroneously inverted the sense of the test. For the pedants on the net, the C.O.F. of the first statement is of course if (A = f1() - 2 || A = f2() - 3 || A = f3() - 4) Pardon my flatulence.
byron@archone.tamu.edu (Byron Rakitzis) (04/01/91)
In article <13982@helios.TAMU.EDU> byron@archone.tamu.edu (Byron Rakitzis) writes: >For the pedants on the net, the C.O.F. of the first statement is of course > > if (A = f1() - 2 || A = f2() - 3 || A = f3() - 4) > >Pardon my flatulence. Whoa, am I beet-red! I'll try not to post to comp.lang.c for another month in repentance. Even the second attempt at COF is way wrong. Last try: (though this one doesn't look as horrible as the one above) if ((A = f1()) - 2 || (A = f2()) - 3 || (A = f3()) - 4) ("not to put too fine a point on it," as the British say.)
volpe@camelback.crd.ge.com (Christopher R Volpe) (04/01/91)
In article <20137@alice.att.com>, ark@alice.att.com (Andrew Koenig) writes: |>A while ago I remember a big argument about the difference between |>code generated by a particular compiler for this: |> |> a=b-c; |> if(a) |> |>and for this |> |> if(a=b-c) Are a,b,and c all of type "int"? [Deleted description of implementation that gave different results.] |>I believe that this behavior on the part of the compiler |>is entirely reasonable. Even if it's completely non-conforming? |>-- |> --Andrew Koenig |> ark@europa.att.com ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
volpe@camelback.crd.ge.com (Christopher R Volpe) (04/02/91)
In article <18099@crdgw1.crd.ge.com>, I wrote |>In article <20137@alice.att.com>, ark@alice.att.com (Andrew Koenig) writes: |>|>I believe that this behavior on the part of the compiler |>|>is entirely reasonable. |> |>Even if it's completely non-conforming? |> Nevermind. I checked and noticed that the behavior is undefined in case of an overflow. (I thought it was just an implementation defined result, and therefore the value of the expression is all that matters, and that would be the same in each case.) Now, if a,b, and c were unsigned... ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
markh@csd4.csd.uwm.edu (Mark William Hopkins) (04/02/91)
In article <13983@helios.TAMU.EDU> byron@archone.tamu.edu (Byron Rakitzis) writes: >Last try: (though this one doesn't look as horrible as the one above) > > if ((A = f1()) - 2 || (A = f2()) - 3 || (A = f3()) - 4) THere you go! I knew if I looked far enough down the article list, I'd see a correction. :) My return example should not read: > (Op = FindOp(S)) && return Op->Type || > (Sym = NewSym(S)) & return Sym->Index; but > return (Op = FindOp(S))? Op->Type: (Sym = NewSym(S)), Sym->Index; I keep on forgetting that in their infinite wisdom the Standard Bearers forgot to make return X a void expression. I'll be sure to add that feature in my next compiler...
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/02/91)
In article <18099@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: > In article <20137@alice.att.com>, ark@alice.att.com (Andrew Koenig) writes: > [Deleted description of implementation that gave different results.] > |>I believe that this behavior on the part of the compiler > |>is entirely reasonable. > Even if it's completely non-conforming? I believe the original post contained a phrase like ``upon overflow.'' Nothing's guaranteed for ints upon overflow. I'm not sure if your CPU is allowed to explode, but you're allowed to get weird results. ---Dan
wirzenius@cc.helsinki.fi (Lars Wirzenius) (04/02/91)
In article <10654@uwm.edu>, markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: > [about converting syntax-changing macros into cleartext] > I use my own scanner-based program to alter variable names and macros in other > peoples' source all the time. It's nothing. It's unnecessary, nonproductive extra work. That's the whole point. -- Lars Wirzenius wirzenius@cc.helsinki.fi
em@dce.ie (Eamonn McManus) (04/03/91)
ark@europa.att.com (Andrew Koenig) writes: >It turned out that the effects differed if the subtract >caused an overflow (call it underflow if you like) with a >zero result. In the first case, the test would show that >a==0. In the second, the condition code would show an >overflow. Overflow is not the same as zero, so the test >would fail. Was this a 1s-complement machine? A sane 2s-complement machine can't produce 0 on subtraction unless the numbers are equal. , Eamonn
markh@csd4.csd.uwm.edu (Mark William Hopkins) (04/03/91)
In article <1991Apr2.122448.5798@cc.helsinki.fi> wirzenius@cc.helsinki.fi (Lars Wirzenius) writes: >In article <10654@uwm.edu>, markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: >> [about converting syntax-changing macros into cleartext] >> I use my own scanner-based program to alter variable names and macros in other >> peoples' source all the time. It's nothing. > >It's unnecessary, nonproductive extra work. That's the whole point. Not when that and other processes of change leave a permanent imprint of the entire source on you, thus causing you to unwittingly memorize the whole thing and know every little nook and cranny of its structure and functioning. Unproductive indeed...
wirzenius@cc.helsinki.fi (Lars Wirzenius) (04/04/91)
In article <10700@uwm.edu>, markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: >>It's unnecessary, nonproductive extra work. That's the whole point. > > [changing macros/identifiers makes you learn the source well] It's unproductive because it forces you to study larger amounts of code than would otherwise be necessary, if you only need to make small changes. -- Lars Wirzenius wirzenius@cc.helsinki.fi
bhoughto@nevin.intel.com (Blair P. Houghton) (04/04/91)
In article <6773:Apr116:28:2991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >I believe the original post contained a phrase like ``upon overflow.'' >Nothing's guaranteed for ints upon overflow. I'm not sure if your CPU is >allowed to explode, but you're allowed to get weird results. No bet when "the behavior is undefined." And to answer Chris' question, if the type of the two things is unsigned, there can be no overflow (underflow) (I'm 2.83 miles from my copy or I'd quote you chapter and verse, of course), so they couldn't be unsigned and behave in an undefined manner. --Blair "It's best to be precise, though that doesn't imply accurate..."
ark@alice.att.com (Andrew Koenig) (04/05/91)
In article <calypso@dce.ie> em@dce.ie (Eamonn McManus) writes: > Was this a 1s-complement machine? A sane 2s-complement machine can't > produce 0 on subtraction unless the numbers are equal. I think it was a 2's complement machine with weird behavior on overflow. -- --Andrew Koenig ark@europa.att.com
cudcv@warwick.ac.uk (Rob McMahon) (04/11/91)
In article <571@bria> uunet!bria!mike writes: >Is there a flavor of preprocessor that unwinds *just* the #define's, and >leaves the rest alone? Yup, it's called `scpp'. I'm sure I got it off comp.sources.all (or was it mod.sources ...): /* * scpp.c - main processing for the selective C preprocessor, scpp. * * Copyright (c) 1985 by * Tektronix, Incorporated Beaverton, Oregon 97077 * All rights reserved. * * Permission is hereby granted for personal, non-commercial * reproduction and use of this program, provided that this * notice and all copyright notices are included in any copy. */ DESCRIPTION Scpp concatenates the input files (or reads standard-in, if no file is given), interprets all references to given mac- ros, leaving the rest of the file(s) unaltered, then writes the result to standard-out. It is helpful in removing con- ditionally compiled code or misleading macros from a file. AUTHOR Brad Needham, Tektronix, Inc. Occasionally it's very useful. Cheers, Rob -- UUCP: ...!mcsun!ukc!warwick!cudcv PHONE: +44 203 523037 JANET: cudcv@uk.ac.warwick INET: cudcv@warwick.ac.uk Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England