[comp.lang.c] When do you use "if

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