[comp.lang.c] Comma operator

swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) (01/14/88)

I'd never used the comma operator before (except in for() statements), so
today I thought I would see what it does.  I did the following program.

#include <stdio.h>

main()
{
 int i=0,j;

 /* assignment code goes here */
 printf("%d %d\n",i,j);
}

in place of the comment up there I put the following different things...

1) j = i,i++;
2) j = i,++i;
3) j = i;
   i++;
4) j = i;
   ++i;
5) j = i++;

All five gave the answer "1 0," and (using Turbo C) they all generate the
same amount of code (OBJ = 223, EXE = 5408).  I assume by this that they
generated the same exact code, though I was too lazy to check.  So, what is
the advantage of using the comma operator other than to squeeze everything
on to one line?

------------------------------------------------------------------
Frank Swarbrick                   |  "Ignorance and prejudice --
swarbric@tramp.UUCP               |   And fear walk and in hand."
swarbric@tramp.Colorado.EDU       |                         --RUSH
...!{hao|nbires}!boulder!tramp!swarbric

chris@mimsy.UUCP (Chris Torek) (01/14/88)

[More operator drivel :-) ]

In article <3819@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU
(SWARBRICK FRANCIS JOHN) writes:
>I'd never used the comma operator before (except in for() statements)....
[five examples deleted]
>All five gave the answer "1 0," and (using Turbo C) they all generate the
>same amount of code (OBJ = 223, EXE = 5408).

They should; semantically, they were all the same.

>So, what is the advantage of using the comma operator other than
>to squeeze everything on to one line?

Not `one line', but rather `one expression', such as is required in
`for' statements.  Comma expressions can also be useful in translating
a function to a macro:

	/*
	 * Get the next nybble.  This is an expression rendition of
	 *	if (--pk->pk_1nyb < 0) {
	 *		pk->pk_1nyb = 1;
	 *		pk->pk_c = nextbyte(pk);
	 *		return (pk->pk_c >> 4);
	 *	} else
	 *		return (pk->pk_c & 0xf);
	 */
	#define	nextnyb(f) \
		(--(pk)->pk_1nyb < 0 ? \
		 ((pk)->pk_1nyb = 1, ((pk)->pk_c = nextbyte(pk)) >> 4) : \
		 (pk)->pk_c & 0xf)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

rsalz@bbn.com (Rich Salz) (01/14/88)

>[what's] the advantage of using the comma operator

One use is in when you are only interested in side-effects, followed shortly
by a test:
	for ( ; ; ) {
	    readorexit();
	    if (satisfied())
		break;
	    ...
	}

	while (readorexit(), !satisfied()) {
	    ...
	}

Or when you want to tie two actions tightly together:
	while (argc--, *++argv)
	    ...

Perhaps the most common use is when you're writing a macro:
	#define SWAP(a, b, temp)  temp=a, a=b, b=temp
You can't write this the "obvious" way:
	#define SWAP(a, b, temp)  {temp=a, a=b, b=temp}
because, someone will write
	if (test(a, b)) SWAP(a, b, temp);
	else abort();
-- 
For comp.sources.unix stuff, mail to sources@uunet.uu.net.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/14/88)

In article <3819@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>So, what is the advantage of using the comma operator other than to squeeze
>everything on to one line?

There are two primary legitimate uses for the comma (sequencing) operator,
typified by:

	for ( i = n, p = array; *p != 0; --i, ++p )
		;

where the comma operator permits multiple operations in each part of the
for(), and

	#ifndef lint
	#define	MmAllo( t )	((t *)Mm_QAllo( sizeof(t) ))
	#else
	#define	MmAllo( t )	((void)Mm_QAllo( sizeof(t) ), (t *)0)
	#endif

where the comma operator permits multiple operations in producing a single
value for an expression.

boemker@hpfcdc.UUCP (01/15/88)

> Perhaps the most common use is when you're writing a macro:
> 	#define SWAP(a, b, temp)  temp=a, a=b, b=temp
> You can't write this the "obvious" way:
> 	#define SWAP(a, b, temp)  {temp=a, a=b, b=temp}
> because, someone will write
> 	if (test(a, b)) SWAP(a, b, temp);
> 	else abort();

OK, I'm feeling like a brick... Why can't I write it the
"obvious" way?

nobody@ism780c.UUCP (Unprivileged user) (01/15/88)

In article <3819@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:

>So, what is
>the advantage of using the comma operator other than to squeeze everything
>on to one line?

At least one use is in a macro, for example:

       #define foo(a,b) ( (x=(a)+(b)) , (y=(a)-(b) )

If the macro were written as:

       #define foo(a,b) { (x=(a)+(b)) ; (y=(a)-(b) }

then it could only be used in the context of a statement.  The first version
is an expression so it can be used where a function reference is allowed.
The value of the first macro is the value assigned to y (which of course may
not be the same as a-b).  The second macro has no value.

     Marv Rubinstein -- Interactive Systems

dhesi@bsu-cs.UUCP (01/16/88)

I respectfully suggest that the comma operator be used only where it is
essential, and not for convenience.

Why?  Because of the following strange situation.  The comma operator
is one of the features of C that is used only rarely, the only common
usages being in for loop expressions and in macros.  For this reason
compiler writers may not test it as exhaustively as they might, for
example, test assignments or arithmetic operators.

So it is more likely that your code will break because of a
compiler bug if you use comma operators in peculiar situations.

I base this statistical conclusion on just one line of C code that I
wrote, that annoyed several C compilers on different flavors of UNIX.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

kurt@hi.UUCP (01/17/88)

In article <1866@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>I respectfully suggest that the comma operator be used only where it is
>essential, and not for convenience.
>
>Why?  Because of the following strange situation.  The comma operator
>is one of the features of C that is used only rarely, the only common
>usages being in for loop expressions and in macros.  For this reason

I commonly use the comma operator in many other "peculiar" places (in
expression by passed to functions, loops, if statements, etc.) because
of convenience or need.  If C didn't have these convenieces, I would
us another language.

>compiler writers may not test it as exhaustively as they might, for
>example, test assignments or arithmetic operators.

The comma operator is as important as any other operator in C.  Should
we restrict the use of "=" because compiler writers may not test it
exhaustively.  It is the compilers writers job to implement the language
to spec (K&R, ANSI, or whatever).  If they can't handle it, then they
should find a new job.

>So it is more likely that your code will break because of a
>compiler bug if you use comma operators in peculiar situations.

Any peculiar situation is more likely to bring out a compiler
bug.  But suggesting programmers use less convenent operators is
not the solution.   What is the solution?  Better compilers (and
compiler writers :-).

>I base this statistical conclusion on just one line of C code that I
>wrote, that annoyed several C compilers on different flavors of UNIX.
>-- 
>Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

I base my conclusions on absolutely no statistics, just common sense.

-- 
	Kurt (zeilenga@hc.dspo.gov)

jamesa%betelgeuse@Sun.COM (James D. Allen) (01/18/88)

The comma operator is one of the things that makes C what it is. For example
	while (A, B)
is equivalent to
	for (A; B; A)
and generates less code on most compilers.  The latter may be considered
more readable, but that seems like evidence of a mental block.

Apropos of "comma in macro definition" here are some excerpts from
"real code".  The program is used to solve the "Logic Puzzles" in
Dell Crosswords magazine although it could be adapted for related problems.
Logic propositions are represented, converted directly into compiled C,
and all solutions are found (through backtracking).

Logic propositions can be nested arbitrarily.  'AND' is implied by
concatenation, 'OR' requires an "EITHER...OR...OR...OR...END_EITHER"
as in the example:

/*
 * Clue 3) Tom and Janice were on their honeymoon but one of them
 * spent the whole time eating.
 */
	MRS_AND_MR(JANICE, TOM)
	EITHER
		IS_TRUE(TOM, EAT)
	OR
		IS_TRUE(JANICE, EAT)
	END_EITHER

Here are some of the relevant "#defines":

#define	EITHER		if (Psol[1] = Psol[0], ! setjmp((++Psol)->jb)) {
#define	OR		} else EITHER
#define	TRY_AGAIN	longjmp((Psol--)->jb, 1)
#define	END_EITHER	} else TRY_AGAIN;

The interesting macro is "EITHER".  It copies and pushes a large
structure representing the problem state:  "Psol[1] = Psol[0], ++Psol",
and sets a checkpoint for later backtracking:  "setjmp()".  I didn't
see a way to do this without the "," operator. (avoid variable number of
"}" in END_EITHER).

If there's interest I'll post the program.

tim@amdcad.AMD.COM (Tim Olson) (01/18/88)

In article <5080013@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes:
| > Perhaps the most common use is when you're writing a macro:
| > 	#define SWAP(a, b, temp)  temp=a, a=b, b=temp
| > You can't write this the "obvious" way:
| > 	#define SWAP(a, b, temp)  {temp=a, a=b, b=temp}
| > because, someone will write
| > 	if (test(a, b)) SWAP(a, b, temp);
| > 	else abort();
| 
| OK, I'm feeling like a brick... Why can't I write it the
| "obvious" way?


Because it would expand to

	if (test(a, b)) {temp=a, a=b, b=temp}; <-- note semicolon
	else abort();
	
The semicolon at the end of the swap is a null statement, which makes
the 'else' construct illegal, since it doesn't directly follow the statement of
the if.

	-- Tim Olson
	Advanced Micro Devices
	(tim@amdcad.amd.com)
	

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/18/88)

In article <5080013@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes:
>... Why can't I write it the "obvious" way?

Observe the extra semicolon you would get, which would make the following
"else" invalid syntax (or perhaps it would link up with the wrong "if").

By the way, I don't think there IS a good way to write a generic swap
macro.  Didn't we go over this about a year ago?

fnf@mcdsun.UUCP (Fred Fish) (01/19/88)

>In article <1866@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>>I base this statistical conclusion on just one line of C code that I
>>wrote, that annoyed several C compilers on different flavors of UNIX.

In article <22902@hi.unm.edu> zeilenga@hc.dspo.gov (Kurt Zeilenga) writes:
>I base my conclusions on absolutely no statistics, just common sense.

Practicality wins over common sense every time.  A correctly designed
transportation vehicle would never permit bodily damage to it's occupants.
That doesn't stop me from wearing my seatbelt.

-Fred
-- 
# Fred Fish    hao!noao!mcdsun!fnf    (602) 438-3614
# Motorola Computer Division, 2900 S. Diablo Way, Tempe, Az 85282  USA

pardo@june.cs.washington.edu (David Keppel) (01/19/88)

[ Don't use comma op because it may not be very well tested ]
[ Go ahead and use it -- it will work ]

The comma operator is guaranteed (K&R pg. 192, sect 7.15) to evaluate
left to right and return the value of the right operand.  Most of the time
that the comma operator is used, neither the order or the return value is
used, but because of the C guarantee, compiler optimizations may be wasted.

On the other hand, in most of the situations where the comma operator is
used, there is no alternative legal C for the code, so we ignore the lost
optimization.  Simply using the comma opeator, however, to group related
code may result in slower code.

I therefore _suggest_ that using the comma operator only where necessary
is a good idea if you are writing time-critical code.

Gee, wouldn't it be nice if we could do:

	for ({i = 0; sum = 0;};  i < limit;  ++i)  sum += a[i];


    ;-D on  (I was an undercover operator in the ...)  Pardo

swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) (01/19/88)

In article <7120@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>By the way, I don't think there IS a good way to write a generic swap
>macro.  Didn't we go over this about a year ago?

#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))

Try that, and tell me what you think.  A super-genius friend of mine figured
it out.  He says it will work for anything (int, char *, etc.).  But it
sure boggles my mind...

------------------------------------------------------------------
Frank Swarbrick                   |  "Ignorance and prejudice --
swarbric@tramp.UUCP               |   And fear walk and in hand."
swarbric@tramp.Colorado.EDU       |                         --RUSH
...!{hao|nbires}!boulder!tramp!swarbric

garys@bunker.UUCP (Gary M. Samuelson) (01/19/88)

In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>In article <7120@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>>By the way, I don't think there IS a good way to write a generic swap
>>macro.  Didn't we go over this about a year ago?

I don't think it was that long ago.

>#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
>
>Try that, and tell me what you think.  A super-genius friend of mine figured
>it out.  He says it will work for anything (int, char *, etc.).  But it
>sure boggles my mind...

Who told him he was a genius?  Self-proclaimed, no doubt.

How about float or double? Structures?
Suppose either a or b have side effects? (e.g., swap( *x++, *y++ ))
What is the value of a macro which performs 6 operations, instead
of the three I want?  (t = a; a = b; b = t)
Suppose a and b are aliases?
How is the exclusive-or of two pointers defined?  (It isn't, at
least not portably).

Yes, it's a clever macro.  Yes, under some conditions it does the
right thing.  I even know why it works.  But I wouldn't use it;
the straightforward approach is much better.  So it takes another
variable; so what?  Are people afraid we'll run out?

My first maxim of programming is this:  Code will be read more
than written; therefore it is more important to be easily read
than easily written.

Gary Samuelson

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/19/88)

In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
>He says it will work for anything (int, char *, etc.).

This is one of the oldest tricks in the book.  However, it does NOT
work for all data types, certainly not for pointers and it's not
even clear how to try to interpret it for structures.

swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) (01/20/88)

Re: that swap macro I posted.

  Well he is definatly a genius, but that's beside the point.  I guess neither
of us really tested it.  I only tested it for ints, but I really didn't think
it would work for anything else.  He told me it would, so I believed him.
Maybe I misunderstood him.

------------------------------------------------------------------
Frank Swarbrick                   |  "Ignorance and prejudice --
swarbric@tramp.UUCP               |   And fear walk and in hand."
swarbric@tramp.Colorado.EDU       |                         --RUSH
...!{hao|nbires}!boulder!tramp!swarbric

mrd@sun.mcs.clarkson.EDU (Michael R. DeCorte) (01/20/88)

>   Gee, wouldn't it be nice if we could do:
>
>       for ({i = 0; sum = 0;};  i < limit;  ++i)  sum += a[i];

I would like something to the effect

int x;

printf("%d\n", {int a;.....; a=x;});

in others words, a block can return a value. Gee think of the #defines
you could make

Michael DeCorte
mrd@clutx.clarkson.edu
mrd@clutx.bitnet

ix426@sdcc6.ucsd.EDU (tom stockfish) (01/20/88)

In article <4006@june.cs.washington.edu> pardo@uw-june.UUCP (David Keppel) writes:
XX[ Don't use comma op because it may not be very well tested ]
XX[ Go ahead and use it -- it will work ]
X....  Simply using the comma opeator, however, to group related
Xcode may result in slower code.

The comma operator is no more stringent a sequence point than semicolon is.
So how could this mean slower code?
-- 

||  Tom Stockfisch, UCSD Chemistry   tps@chem.ucsd.edu

pardo@june.cs.washington.edu (David Keppel) (01/20/88)

[ how could the comma operator cause slower code? ]

Because the comma operator guarantees an order of evaluation on two
statements that the compiler might otherwise rearrange to produce more
efficient code.

As a brain-dead example:

	    ++x, ++y;
	    if (x % n) { ... }

If the comma was replaced by a semicolon, the compiler could rewrite it as

	    ++y;
	    if (++x % n) { ... }

Which would be faster on many machines.

I'm not saying that this happens all the time or that you should worry
about it in the normal case, but if you are writing code where you need
all the optimization you can get (particularly if your compiler does good
code-motion) then you might want to worry that the compiler can't optimize
that extra cycle (because the comma operator guarantees order of execution).

	;-D on  (speed, like cocaine, is highly illegal)  Pardo

rab@mimsy.UUCP (Bob Bruce) (01/21/88)

In article <11335@brl-adm.ARPA> mrd@sun.mcs.clarkson.EDU (Michael R. DeCorte) writes:
>I would like something to the effect
>
>int x;
>
>printf("%d\n", {int a;.....; a=x;});
>
>in others words, a block can return a value. Gee think of the #defines
>you could make

Some compilers, including the Gnu compiler from the Free Software
Foundation, offer this as a language extension.  It comes in
handy, especially when writing complicated macros.

>Michael DeCorte
>mrd@clutx.clarkson.edu
>mrd@clutx.bitnet

 Bob Bruce
 rab@mimsy.umd.edu
 uunet!mimsy!rab

rck@ihuxv.ATT.COM (R. C. Kukuk) (01/21/88)

In article <7137@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> >He says it will work for anything (int, char *, etc.).
> 
This oldie fails when a == b.  Why?  Think about it.


Re: Another discussion in this news group --

Note that I said "a == b"; not "a = b". :-)

Ron Kukuk
AT&T Bell Labs

jfc@athena.mit.edu (John F Carr) (01/21/88)

In article <4018@june.cs.washington.edu> pardo@uw-june.UUCP (David Keppel) writes:
>[ how could the comma operator cause slower code? ]

      Because the comma operator guarantees an order of evaluation on two
      statements that the compiler might otherwise rearrange to produce more
      efficient code.

      	    ++x, ++y;
      	    if (x % n) { ... }

      If the comma was replaced by a semicolon, the compiler could rewrite it as

      	    ++y;
      	    if (++x % n) { ... }

      Which would be faster on many machines.


I thought that "," and ";" both guaranteed order of evaluation.
I have not heard anything to the contrary.  The difference, as I 
see it, is that "," orders statements within a statement (I don't
remember which are called statements and which expressions).  I 
have always assumed that ;'s determined the order of evaluation
but that an optimizing compiler could reorder any statements as long
as the results are identical with the results of the written order.

Is there any reason that ";" seperated statements can be reordered 
but "," seperated statements can't be?

  --John Carr   (jfc@ATHENA.MIT.EDU)

pardo@june.cs.washington.edu (David Keppel) (01/22/88)

----

John F. Carr (jfc@athena.mit.edu) writes:
>In article <4018@june.cs.washington (pardo@cs.washtinton.edu) writes:
>>[ how could the comma operator cause slower code? ]
>>
>>  The comma operator guarantees an order of evaluation on two statements
>>  that the compiler might otherwise rearrange to produce better code.
>>
>>     	    ++x, ++y;  	    if (x % n) { ... }
>>
>>  If the comma was replaced by a semicolon, the compiler could rewrite it as
>>
>>     	    ++y;     	    if (++x % n) { ... }
>>
>>  Which would be faster on many machines.
>
>I thought that "," and ";" both guaranteed order of evaluation.
>I have not heard anything to the contrary.
>[...]
>have always assumed that ;'s determined the order of evaluation
>but that an optimizing compiler could reorder any statements as long
>as the results are identical with the results of the written order.

To which harvard!wjh12!genrad!jpn@beaver (John P. Nelson) adds:
: If the compiler is allowed to rewrite it when a semicolon is used,
: then it is ALSO allowed to rewrite it when a COMMA is used.  Semicolons
: are "sequence points" just like commas.  The difference is only that the
: comma is a sequence point that is PART of an expression, the semicolon is
: a sequence point that also delimits statements.
:
: Remember that a sequence point is a place where the program must act
: AS IF the code is compiled exactly as written.  In your example, the
: compiler is free to reorder the increment of x, because (unless x is
: declared as "volatile") there is no way for the program to reference
: the value of x before the expression in the "if" statement.  On the
: other hand, if it was:
:
:	++x, y = x + 2;
:
: THEN the sequence point at the comma becomes significant:  The compiler
: CANNOT delay incrementing x until after the semicolon.  See?

K&R says that the order of evaluation is guaranteed.  Guaranteed _could_
be in terms of sequence points.  Somebody who does a lot of systmes work
might say:

    int	*ctrl_p = DISK_CTRL_REGISTER;
    int	*out_p = DISK_OUT_REGISTER;

    *ctrl_p = SETUP, *out_p = GO;

which _relies_ on the evaluation order being guaranteed in a
stronger way than is provided by sequence points.  If I were selling
a compiler I would write it so that code like the above wouldn't
break (C is a systems programming language, eh?), but unfortunately
this "turns off" some optimizations.  This isn't an issue until

(a) somebody needs the last few cycles of performance out of some code and
(b) they use  s1,s2;  where  s1;s2;  would do.

This doesn't say that all compilers are written this way.  Only that you
can't rely on all compilers being written the other (sequence point
guarantee) way.  As I said before, you only need to worry about this if
you need to squeeze the last few cycles out of something.

Anybody with ANSI or who writes C compilers like to comment on this?
Please send e-mail, I'll summarize.

    ;-D on  (Give me a pointer and I'll derefernce the world)  Pardo
    pardo@cs.washington.edu	ucbvax!uw-beaver!uw-june!pardo

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/22/88)

In article <3887@sigi.Colorado.EDU>, swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
> #define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> 
> Try that, and tell me what you think.  A super-genius friend of mine figured
> it out.  He says it will work for anything (int, char *, etc.).  But it
> sure boggles my mind...
It is a simple mathematical propterty of XOR.  That is :
    a = a xor b
    b = a xor b
    a = b xor a

swaps the values of A and B.  My opsys book had that in it.  A systems
programming course offered here at NMT has that as one of the home
work problems (at least the time I took it).  You can find this device
in lots of places.  The first place that I saw it was in RSTS/E COMMOM.MAC
file, where it was used to swap two registers, w/o the need for a temp
storage.




-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/22/88)

In article <2382@ihuxv.ATT.COM> rck@ihuxv.ATT.COM (R. C. Kukuk) writes:
>> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
>> >He says it will work for anything (int, char *, etc.).
>
>This oldie fails when a == b.  Why?  Think about it.

I did.  I still don't see why it fails.


The macro is equivalent to (assuming a and b are either vars or constants of
the same type and that type allows the ^ operator) the following evaluated in
the order presented:

a = a ^ b
b = a ^ b
a = a ^ b


Here is an example where a == b  (numbers given in binary)

Let a = b = 00101101

swap(a,b):
a = a ^ b === 00101100 ^ 00101101 === 00000000
b = a ^ b === 00000000 ^ 00101101 === 00101101
a = a ^ b === 00000000 ^ 00101101 === 00101101

Hence, a = b = 00101101.  QED
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

chris@mimsy.UUCP (Chris Torek) (01/22/88)

[One-line summary: some people are suffering from the illusion that
`;' allows optimisations that `,' does not.]

In article <4037@june.cs.washington.edu> pardo@june.cs.washington.edu
(David Keppel) provides the following example:
>    int	*ctrl_p = DISK_CTRL_REGISTER;
>    int	*out_p = DISK_OUT_REGISTER;
>
>    *ctrl_p = SETUP, *out_p = GO;
>
>which _relies_ on the evaluation order being guaranteed in a
>stronger way than is provided by sequence points.

Yes.  However, the same code written this way:

	*ctlr_p = SETUP;
	*out_p = GO;

*also* depends on order in a stronger way than is provided by
sequence points.  The *only* way to guarantee proper operation
under dpANS rules is to write

	volatile int *ctlr_p = DISK_CTRL_REGISTER;
	volatile int *out_p = DISK_OUT_REGISTER;

and in such a case the compiler is required to generate
equivalently ordered code for either version (`,' or `;').
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

blarson@skat.usc.edu (Bob Larson) (01/22/88)

In article <4037@june.cs.washington.edu> pardo@uw-june.UUCP (David Keppel) writes:
>    int	*ctrl_p = DISK_CTRL_REGISTER;
>    int	*out_p = DISK_OUT_REGISTER;
>
>    *ctrl_p = SETUP, *out_p = GO;
>
>which _relies_ on the evaluation order being guaranteed in a
>stronger way than is provided by sequence points.

Ansi C (all recent drafts, not yet a standard) adds the keyword
"volitile" for exactly this reason.  Change the declarations to

int *volitile ctrl_p;
int *volitile out_p;

and an ANSI compiler will not be allowed to rearange.

(I got this out of this group, I hope I have the volitile in the right
place.)
--
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

wswietse@eutrc3.UUCP (Wietse Venema) (01/22/88)

In article <11335@brl-adm.ARPA>, mrd@sun.mcs.clarkson.EDU (Michael R. DeCorte) writes:
> I would like something to the effect
> 
> int x;
> 
> printf("%d\n", {int a;.....; a=x;});
> 
> in others words, a block can return a value. Gee think of the #defines
> you could make

Michael, ever thought of trying

	foo(..) {int a;...;return(a=x);}

	printf("%d\n",foo(...));

Gee think of the functions you could make :-)

Wietse (...!mcvax!eutrc3!wswietse) Venema

djones@megatest.UUCP (Dave Jones) (01/23/88)

in article <2382@ihuxv.ATT.COM>, rck@ihuxv.ATT.COM (R. C. Kukuk) says:
> 
> In article <7137@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
>> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
>> >He says it will work for anything (int, char *, etc.).
>> 
> This oldie fails when a == b.  Why?  Think about it.
> 
> 
> Re: Another discussion in this news group --
> 
> Note that I said "a == b"; not "a = b". :-)
> 
> Ron Kukuk
> AT&T Bell Labs

I think some clarification is in order:  What Ron means is that

  swap(X,X)

will not work.  Sets X to 0 always.

  { int a; int b; a = 5; b = 5; swap(a,b); }

works just fine.



		Dave Jones
		Megatest Corp.

ok@quintus.UUCP (Richard A. O'Keefe) (01/23/88)

In article <3476@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
> In article <2382@ihuxv.ATT.COM> rck@ihuxv.ATT.COM (R. C. Kukuk) writes:
> >> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
> >> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> >> >He says it will work for anything (int, char *, etc.).
> >
> >This oldie fails when a == b.  Why?  Think about it.
> 
> I did.  I still don't see why it fails.
> 
	swap(a, a);
sets a to 0, whatever its previous value was.  If you do
	swap(*p, *q);
it can easily happen that p==q, in which case you get this problem.

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/24/88)

In article <10293@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>The *only* way to guarantee proper operation
>under dpANS rules is to write
>
>	volatile int *ctlr_p = DISK_CTRL_REGISTER;
>	volatile int *out_p = DISK_OUT_REGISTER;

Or, for the sake of argument and abandoning all hope of efficiency, one
could say:

     extern unsigned *read_disk_ctrl_register (void);
     extern void write_disk_ctrl_register (unsigned);

If compiled separately, and until globally optimizng *linkers* are
developed, even a globally optimizing compiler really has no choice but
to respect an order such as:

     write_disk_ctrl_register (RESET);		/* must be done first */
     status = read_disk_ctrl_register ();	/* must be done second */
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

franka@mmintl.UUCP (Frank Adams) (01/26/88)

In article <2382@ihuxv.ATT.COM> rck@ihuxv.ATT.COM (R. C. Kukuk) writes:
|> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
|> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
|This oldie fails when a == b.

I believe you mean &a == &b.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

ian@puivax.UUCP (Ian Wilson) (01/28/88)

In article <564@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>> >> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
>> >> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
>
>	swap(a, a);
>sets a to 0, whatever its previous value was.  If you do
>	swap(*p, *q);
>it can easily happen that p==q, in which case you get this problem.

I am posting this because I once had a *useful* application of
this way of swapping two pieces of storage without using any
temporary storage. Using an image processor with an asymmetric
ALU, ie. it expected operand A to come from image memory A and
operand B from B, it enabled me to swap memories in 3 operations:

	1. A ^= B
	2. B ^= A
	3. A ^= B

(At least the ALU knew how to xor!!).

Each image memory was 1/4Mb, so doing it this way (90ms) was OK,
compared with the prospect of moving 2x1/4M off to mass storage
and back again.....

The transformation works whatever the values of A & B happen to
be - exclusive or being the only information-preserving logical
operation. So the original `swap' macro may or may not be very
useful but the principle is correct.

 ---- ccicpg!puivax!ian

jay@splut.UUCP (Jay Maynard) (02/01/88)

In article <564@cresswell.quintus.UUCP>, ok@quintus.UUCP (Richard A. O'Keefe) writes:
> > In article <2382@ihuxv.ATT.COM> rck@ihuxv.ATT.COM (R. C. Kukuk) writes:
> > >> In article <3887@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
> > >> >#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> > >This oldie fails when a == b.  Why?  Think about it.
> 	swap(a, a);
> sets a to 0, whatever its previous value was.  If you do
> 	swap(*p, *q);
> it can easily happen that p==q, in which case you get this problem.

Let's explode the macro, and see what it does:

p = 5; q = 5;
swap(p,q);

the swap macro becomes:
((p) = ((q) = ((p) = (p) ^ (q)) ^ (q)) ^ (p))

stripping redundant parentheses:
p = (q = (p = p ^ q) ^ q) ^ p

substituting variables, from the inside out:
p = (q = (p = 5 ^ 5) ^ q) ^ p     (assigns 0 to p, temporarily)
p = (q = 0 ^ 5) ^ p               (assigns 5 to q)
p = 5 ^ 0                         (assigns 5 to p)

This case still works. As pointed out before, though, this macro has other
problems.

-- 
Jay Maynard, K5ZC (@WB5BBW)...>splut!< | GEnie: JAYMAYNARD  CI$: 71036,1603
uucp: {uunet!nuchat,academ!uhnix1,{ihnp4,bellcore,killer}!tness1}!splut!jay
Never ascribe to malice that which can adequately be explained by stupidity.
The opinions herein are shared by none of my cats, much less anyone else.

franka@mmintl.UUCP (Frank Adams) (02/02/88)

In article <131@puivax.UUCP> ian@puivax.UUCP (Ian Wilson) writes:
>The transformation works whatever the values of A & B happen to
>be - exclusive or being the only information-preserving logical
>operation.

A quibble -- exclusive or is not the only information-preserving (binary)
logical operation.  Equivalence also has this property.  One can also use
equivalence instead of exclusive or in the exchange algorithm.

Of course, equivalence isn't really very different from exclusive or -- just
interchange the role of the zeros and ones, and you get one from the other.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

peter@sugar.UUCP (Peter da Silva) (02/05/88)

In article <3887@sigi.Colorado.EDU>, swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
> #define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))

It is dependent on order of evaluation of assignments. It might work on your
compiler, but it's not guaranteed.

What does "inline" do if you get it to inline a swap routine?
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

swarbric@tramp.Colorado.EDU (Frank Swarbrick) (02/06/88)

In article <1434@sugar.UUCP> peter@sugar.UUCP (Peter da Silva) writes:
:In article <3887@sigi.Colorado.EDU>, swarbric@tramp.Colorado.EDU (SWARBRICK FRANCIS JOHN) writes:
:> #define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
:
:It is dependent on order of evaluation of assignments. It might work on your
:compiler, but it's not guaranteed.
:
:What does "inline" do if you get it to inline a swap routine?

(I'm still recovering from the extreme embarrassment of posting this in the
first place...)

Anyway, I don't know.  What is "inline"?

Frank Swarbrick (and his cat)
swarbric@tramp.UUCP               swarbric@tramp.Colorado.EDU
...!{hao|nbires}!boulder!tramp!swarbric
    "No one can hear when you're Screaming in Digital!"

nair@quintus (01/14/89)

What should this print?

	int x, y;
	printf("%d %d\n", (x = 1, y = 2), x, y);

Shouldn't it be equivalent to:

	int a, x, y;
	a = (x = 1, y = 2);
	printf("%d %d %d\n", a, x, y);

Is there any justification in the first one printing
	2 1 0

Is there God? Why am I here? :-) :-)

Anil Nair

Please reply to nair@quintus.uucp or ...!sun!quintus!nair

w-colinp@microsoft.UUCP (Colin Plumb) (01/14/89)

nair@quintus () wrote:
> What should this print?
> 
> 	int x, y;
> 	printf("%d %d\n", (x = 1, y = 2), x, y);

(I assume you really want a third %d in there.)

It should print 2 <garbage> <garbage>.  If a machine evaluates arguments
left-to-right, it would print 2 1 2, but on many machines, arguments are
pushed right-to-left, and evaluated in the same order.  Thus, x and y
get assigned after their old values have been pushed.

C has never made any guarantees about the order in which arguments to
functions are evaluated; while the comma operator does, the comma between
function arguments is a different beast entirely.

> Shouldn't it be equivalent to:
> 
> 	int a, x, y;
> 	a = (x = 1, y = 2);
> 	printf("%d %d %d\n", a, x, y);

Ah, this is different... there's a sequence point at the ; after the
assignment to a, so it is guaranteed that x and y have their new values
before the call is made.

> Is there any justification in the first one printing
> 	2 1 0

Yes.
-- 
	-Colin (uunet!microsof!w-colinp)

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/14/89)

In article <922@quintus.UUCP> nair@quintus () writes:
>What should this print?
>	printf("%d %d\n", (x = 1, y = 2), x, y);

"Warning -- missing format specifier for one argument".

>Is there any justification in the first one printing
>	2 1 0

[Assuming the format spec was fixed.]
The order in which arguments to functions are evaluated is intentionally
unspecified.  Some implementations do it one way, some another.  In your
case it appears that they were evaluated right-to-left.

chris@mimsy.UUCP (Chris Torek) (01/14/89)

In article <922@quintus.UUCP> nair@quintus writes:
>What should this print?
>
>	int x, y;
>	printf("%d %d\n", (x = 1, y = 2), x, y);

(presumably there is one `%d' missing here.)

Nothing certain.  The invocation contains two commas and *one* comma
operator.  The order of evaluation of the one comma operator is guaranteed,
but the order of the whole mess is not.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

ark@alice.UUCP (Andrew Koenig) (01/15/89)

In article <922@quintus.UUCP>, nair@quintus writes:
> What should this print?
> 
> 	int x, y;
> 	printf("%d %d\n", (x = 1, y = 2), x, y);

Whatever the compiler wants to print.

> Shouldn't it be equivalent to:
> 
> 	int a, x, y;
> 	a = (x = 1, y = 2);
> 	printf("%d %d %d\n", a, x, y);

No.

The arguments of printf are not required to be evaluated
in any particular sequence.

> Is there God? Why am I here? :-) :-)

The first question is too difficult for comp.lang.c
The second can be divided into two parts.

Part 1: `Why?'  This is an extremely difficult question as well,
so it is left as an exercise for the reader.

Part 2: `Am I here?'  Answer: yes.
-- 
				--Andrew Koenig
				  ark@europa.att.com

earleh@eleazar.dartmouth.edu (Earle R. Horton) (01/15/89)

In article <922@quintus.UUCP> nair@quintus () writes:
>What should this print?
>
>	int x, y;
>	printf("%d %d\n", (x = 1, y = 2), x, y);
>
>Shouldn't it be equivalent to:
>
>	int a, x, y;
>	a = (x = 1, y = 2);
>	printf("%d %d %d\n", a, x, y);
>

K&R, 1978, p. 212:

     "Some difficulties arise only when dubious coding practices are
used.  It is exceedingly unwise to write programs that depend on any
of these properties.
     The order of evaluation of function arguments is not specified
by the language..."

     Unfortunately, most beginning programmers assume it is always
left to right.

>Is there any justification in the first one printing
>	2 1 0

     The only thing you are guaranteed to get from code like the first
example is that the first number printed will be 2.  The second two
output values can be any integer value, including the values which you
think should go there.  The compiler writer is free to evaluate
function parameters left-to-right, right-to-left, or even
middle-one-first if that is a more efficient way to do it.
Earle R. Horton. 23 Fletcher Circle, Hanover, NH 03755--Graduate student.
He who puts his hand to the plow and looks back is not fit for the
kingdom of winners.  In any case, 'BACK' doesn't work.

flaps@dgp.toronto.edu (Alan J Rosenthal) (07/29/89)

dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
>I also occasionally use the comma to save braces:
>	if((f = fopen(file, "r")) == NULL)
>		fprintf(stderr, "Can't open %s\n", file), exit(2);

Funny, I use braces to save commas:
	if ((f = fopen(file, "r")) == NULL) {
		fprintf(stderr, "Can't open %s\n", file);
		exit(2);
	}

dooley@helios.toronto.edu (Kevin Dooley) (07/31/89)

In article <1989Jul28.174033.12734@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
>dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
>>I also occasionally use the comma to save braces:
>>	if((f = fopen(file, "r")) == NULL)
>>		fprintf(stderr, "Can't open %s\n", file), exit(2);
>
>Funny, I use braces to save commas:
>	if ((f = fopen(file, "r")) == NULL) {
>		fprintf(stderr, "Can't open %s\n", file);
>		exit(2);
>	}

Can anybody tell me if there is a usage where the comma is 'better'.
By this I mean are there any places where using a comma makes the 
code more readable, efficient, produce cleaner/faster assembler (I
know this is compiler dependant).  It's just that I've never seen a
program with the comma operator where I didn't scream and edit it out.
Am I being hopelessly pedestrian here?

Just curious,
Kevin




-- 
 Kevin Dooley         UUCP - {uunet,pyramid}!utai!helios.physics!dooley
 Physics Dept.        BITNET - dooley@utorphys
 U. of Toronto        INTERNET - dooley@helios.physics.utoronto.ca

plocher%sally@Sun.COM (John Plocher) (08/01/89)

In <918@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:
>Can anybody tell me if there is a usage where the comma is 'better'.

The only place I ever had a real use for the comma operator was when working with
a 3rd party C-ISAM library which had many functions and a large set of error returns.

Call the lib functions copen(), cclose(), cinsert(), cfind()...
These routines would return a value X, where on success X > 0 and was then
used as a magic cookie.  If X < 0 then there were 15 or so error conditions
that could have happened - all but 4 or 5 because of stupid programmer errors
(The routines used structures that HAD to be initialized *just so* &$&%#$%# ).

Output of all this is like:

Trace: copen(structure, FLAG|FLAG, "Filename", blah) => DB_NOTFOUND (File not found)
Trace: ccreate(structure,...) => DB_OK

I actually used __LINE__ and __FILE__ in the ERROR() macro so the output was
more useful still.

    -John Plocher

------------------------------------------------------------------------------------

#ifdef DEBUG

int ERROR_CC;

log(funct, string)
char *funct, *string;
{
	fprintf(stderr,"Trace: %s => %s\n", funct,string);
}

char *errorname( error_cc )
int error_cc;
{
	if (error_cc > 0) return itoa(error_cc);
	else if (error_cc == DB_OK)       return "DB_OK";
	else if (error_cc == DB_NOTFOUND) return "DB_NOTFOUND (File not found)";
	else if (error_cc == DB_BADSTRUCT)return "DB_BADSTRUCT (Invalid DB Struct)";
	else if ...
}

/* Relies on NON-ANSI C Preprocessor behavior ! */

#define ERROR(funct)	(log("funct", errorname(ERROR_CC=funct)), ERROR_CC)
/*
** Call funct() and assign the ret val to ERROR_CC
** Send this value to errorname() so we get an english description of the error
** Send the (string representation) of the function and this english to log()
** Finally, give the poor user the ret value we saved in ERROR_CC
*/

#else	/* not DEBUG */

#define ERROR(funct)	funct

#endif	/* if DEBUG else endif */

main() {
int dbfd;

	init( &structure );
	dbfd = ERROR(copen(structure, FLAG|FLAG, "Filename", blah));
	if (dbfd == DB_NOTFOUND)
	    dbfd = ERROR(ccreate(structure,...));
	if (dbfd < 0)
	    bomb();
}

mpl@cbnewsl.ATT.COM (michael.p.lindner) (08/01/89)

In article <918@helios.toronto.edu>, dooley@helios.toronto.edu (Kevin Dooley) writes:
> In article <1989Jul28.174033.12734@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
> >dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
> >>I also occasionally use the comma to save braces:
> >Funny, I use braces to save commas:
> 
> Can anybody tell me if there is a usage where the comma is 'better'.
> By this I mean are there any places where using a comma makes the 
> code more readable, efficient, produce cleaner/faster assembler (I
> know this is compiler dependant).  It's just that I've never seen a
> program with the comma operator where I didn't scream and edit it out.
> Am I being hopelessly pedestrian here?
> 
>  Kevin Dooley         UUCP - {uunet,pyramid}!utai!helios.physics!dooley

There are only 2 uses of the comma operator which I find acceptable.

1) In a #define, where it is necessary to use multiple expressions:
	#define fatal(E)		(error(E), exit(1))
   I would NEVER NEVER NEVER #define a function macro which was not a
   single, well behaved (ie. parenthesized) expression.  As I understand
   it, this was the primary reason for the origination of the comma operator.

2) In the "modify" part of a for loop:
	for (i = 0; i < 8; j >>=1, i++)
   The reason for this is so within the loop, one can continue without
   skipping the modify of j.

In both these cases, the comma operator contributes to the "maintain-ability"
of the code, by allowing one to write a useful construct which does not
place hidden (non-obvious) restrictions on other parts of the code:
For instance:
	#define fatal(E)		{ error(E); exit(1); }

	x = (y ? z / y : fatal("division by zero"));

or
	for (i = 0; i < 8; i++) {
		if (j & 1)
			continue;
		func();
		j >>= 1;
	}

Both these examples croak, one at compile time, one at run time.

Mike Lindner
attunix!mpl
AT&T Bell Laboratories
190 River Rd.
Summit, NJ 07901

tada@athena.mit.edu (Michael Zehr) (08/01/89)

In article <918@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:
>Can anybody tell me if there is a usage where the comma is 'better'.
>By this I mean are there any places where using a comma makes the 
>code more readable, efficient, produce cleaner/faster assembler (I
>know this is compiler dependant).  It's just that I've never seen a
>program with the comma operator where I didn't scream and edit it out.
>Am I being hopelessly pedestrian here?
>

I agree with you completely.  People seem to use the comma operator to
save lines of code and bytes of text files.  It rarely makes a
difference in the compiled code, and it does make it harder to read.

If you debate the "harder to read" bit, consider this -- the comma
essentially is like putting two statements on one line.  would you
rather read code like:
  puts("it broke."); exit(2);

than:
  puts("it broke.");
  exit(2);

I will qualify the "no comma" rule, though -- sometimes a comma is
required in a macro in order to allow the macro to "return" a value.  of
course, this isn't making code much harder to read because it only
appears in one place, and there is no other solution given the syntax of
tha language.

-michael j zehr

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/01/89)

In article <918@helios.toronto.edu> dooley@helios.physics.utoronto.ca (Kevin Dooley) writes:
>Can anybody tell me if there is a usage where the comma is 'better'.

The comma operator's main legitimate use is in the definition of macros
that are expected to act like function calls but perform actions too
complex for a single (non-comma) expression.

reesd@gtephx.UUCP (David Rees) (08/01/89)

> dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
> >I also occasionally use the comma to save braces:
> >	if((f = fopen(file, "r")) == NULL)
> >		fprintf(stderr, "Can't open %s\n", file), exit(2);

WOuldn't this cause problems based on the order of evaluation? I know
that the evalaution of the variables can be either left to right,
or right-to-left (depending on the machine). Does this mean that the
order of execution would also depend on the machine? Also by using
braces and semi-colons we know exactly what order things are going
to go in. Of course, it does save braces.

		-Dave

peter@ficc.uu.net (Peter da Silva) (08/02/89)

Herewith the only use for the comma operator outside a macro that I can
think of:

	for(init1, init2; test; incr1, incr2)...

For example:

	for(i = 0, c = first(); i < MAX && c != TERM; i++, c = next())
		whatever...;

This can be written, at the cost of some logical relatedness:

	i = 0;
	c = first();
	while(i < MAX && c != TERM) {
		whatever...;
		i++;
		c = next();
	}

Which is IMHO less readable. In addition, if !whatever...;! contains any
!continue! statements, they would have to be implemented as gotos or the
!i++; c = next();! would have to be duplicated.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: peter@ficc.uu.net, +1 713 274 5180. | "The sentence I am now
Personal: peter@sugar.hackercorp.com.   `-_-' |  writing is the sentence
Quote: Have you hugged your wolf today?  'U`  |  you are now reading"

roemer@cs.vu.nl (Roemer Lievaart) (08/02/89)

tada@athena.mit.edu (Michael Zehr) writes:

>If you debate the "harder to read" bit, consider this -- the comma
>essentially is like putting two statements on one line.  would you
>rather read code like:
>  puts("it broke."); exit(2);

>than:
>  puts("it broke.");
>  exit(2);

I often write:

	if (something_goes(wrong) )
		fprintf(stderr, "%s: I give up!\n", argv[0] ) ,
		exit(2) ;

Of course it's no better than using { ; }, but it's not worse either.
____________________________________________________________________________
Roemer B. Lievaart |   Some people are convinced by large gestures, but
Amsterdam, Holland |   get suspicious by arguments.
roemer@cs.vu.nl    | 				-- Nietzsche

grano@kreeta.cs.Helsinki.FI (Juhani Grano) (08/02/89)

	Well, sometimes the comma operator _is_ nice, in my opinion.
Consider the following example:

	foo = 0;
	bar = 0;
	for (i=0; i < burp; i++) {
		rotten_action(foo, bar);
		foo++;
		bar++;
	}

Using the comma operator here produces quite readable result:

	for (foo=0, bar=0, i=0; i < burp; i++, foo++, bar++)
		rotten_action(foo, bar);

But, ah well, I can already imagine the 2<<15 flames I'm gonna receive :-).

Kari. 
------------------------------
Kari Grano				University of Helsinki, Finland
email to: grano@cs.helsinki.fi		Department of CS
	"I've got a thousand telephones that don't ring"

grano@kreeta.cs.Helsinki.FI (Juhani Grano) (08/02/89)

	Ouch... of course I meant expecting 1<<15 flames, not 2<<16 :-)!

Kari.
------------------------------
Kari Grano				University of Helsinki, Finland
email to: grano@cs.helsinki.fi		Department of CS
	"I've got a 1<<15 phones that don't ring"

bph@buengc.BU.EDU (Blair P. Houghton) (08/02/89)

In article <3553@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <1989Jul28.174033.12734@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
>>
>>dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
>>>I also occasionally use the comma to save braces:
>>>	if((f = fopen(file, "r")) == NULL)
>>>		fprintf(stderr, "Can't open %s\n", file), exit(2);
>>
>>Funny, I use braces to save commas:
>>	if ((f = fopen(file, "r")) == NULL) {
>>		fprintf(stderr, "Can't open %s\n", file);
>>		exit(2);
>>	}

Forget I ever said anything.

				--Blair
				  "Flames welcomed cheerily;
				   I'm practicing my /dev/null
				   backhand..."

wen-king@cit-vax.Caltech.Edu (King Su) (08/02/89)

In article <3553@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <1989Jul28.174033.12734@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
<>
>>dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
<>>I also occasionally use the comma to save braces:
>>>	if((f = fopen(file, "r")) == NULL)
<>>		fprintf(stderr, "Can't open %s\n", file), exit(2);
>>
<>Funny, I use braces to save commas:
>>	if ((f = fopen(file, "r")) == NULL) {
<>		fprintf(stderr, "Can't open %s\n", file);
>>		exit(2);
<>	}
>
<Funny, you didn't notice the syntactic error of putting a statement
>as the comma's operand, which may only be an expression...

Funny, you didn't notice that both fprintf(...) and exit(...) are
expressions.

My rule about style is that there is no rule.  You can use NULL, TRUE,
comma, or even goto, as long as the end product is easier to understand
as a result of their use.  You can even change your style from time to
time, if it helps.

-- 
/*------------------------------------------------------------------------*\
| Wen-King Su  wen-king@vlsi.caltech.edu  Caltech Corp of Cosmic Engineers |
\*------------------------------------------------------------------------*/

skilbane@zaphod.axion.bt.co.uk (Steven Kilbane) (08/02/89)

From article <918@helios.toronto.edu>, by dooley@helios.toronto.edu (Kevin Dooley):
> Can anybody tell me if there is a usage where the comma is 'better'.
> By this I mean are there any places where using a comma makes the 
> code more readable, efficient, produce cleaner/faster assembler (I
> know this is compiler dependant).  It's just that I've never seen a
> program with the comma operator where I didn't scream and edit it out.
> Am I being hopelessly pedestrian here?

Well, in addition to the points about macro use, my own _personal_ feeling is
that it can highlight associations:

1	x=5;
	for (c='k';...;..) {

2	for (x=5,c='k';...;..) {

Now, to me, the first form indicates that c will be used in the loop, and that
x might be. The second strongly hints that both c and x will be used in the
loop.

I dunno - maybe I'm just sick.
-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo
Stephen Kilbane                      |Email: skilbane@uk.co.bt.axion
British Telecom Research Laboratories|or smk-a@uk.ac.york.minster (or, if that
Martlesham Heath                     |doesn't work, root@uk.ac.york.softeng - 
Ipswich IP5 7RE (0473 646638)        |not me, but it may be passed on....
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Disclaimer: Who? Me? Nah - must have been someone else when my back was turned!
Quotes: "If silence is golden, music is platinum"
        "'You haven't lived till you've died in MUD' - I live a lot!"
        "(If platinum is to gold, what is to golden?)"[This space to rent]

mpl@cbnewsl.ATT.COM (michael.p.lindner) (08/02/89)

In article <... (names hidden to protect the guilty)
> > dandb@k.gp.cs.cmu.edu (Dean Rubine) writes:
> > >I also occasionally use the comma to save braces:
> > >	if((f = fopen(file, "r")) == NULL)
> > >		fprintf(stderr, "Can't open %s\n", file), exit(2);
> 
> various erroneous discussions of how order of evaluation is wrong
> or that these are statements and can't be used as expressions.

***FLAME ON!***
Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
and fprintf(...) and exit(...) ARE valid expressions in C.
sputter sputter - flame off.

Mike Lindner
attunix!mpl or mpl@attunix.att.com
AT&T Bell Laboratories
190 River Rd.
Summit, NJ 07901

reesd@gtephx.UUCP (David Rees) (08/03/89)

In article <918@helios.toronto.edu>, dooley@helios.toronto.edu (Kevin Dooley) writes:
> Can anybody tell me if there is a usage where the comma is 'better'.
> By this I mean are there any places where using a comma makes the 
> code more readable ....  It's just that I've never seen a
> program with the comma operator where I didn't scream and edit it out.
> Am I being hopelessly pedestrian here?

I am assuming that we mean other than for, while statements etc...

                                  -David

I like the comma operator. I hardly ever use it, but I like it.

decot@hpisod2.HP.COM (Dave Decot) (08/03/89)

> The comma operator's main legitimate use is in the definition of macros
> that are expected to act like function calls but perform actions too
> complex for a single (non-comma) expression.

Another convenient use of the comma operator is in for loops that vary
two variables at once:

    for (count = 0, p = Head; count < MAX && p != NULL; ++count, p = p->next)
    {
	...
    }

Moving one of the initializations above the for statement and one of
the increments into the loop body would eliminate the commas, but would
also make the dual nature of the loop less clear.

Dave Decot

skilbane@zaphod.axion.bt.co.uk (Steven Kilbane) (08/03/89)

From article <2963@solo6.cs.vu.nl>, by roemer@cs.vu.nl (Roemer Lievaart):
> tada@athena.mit.edu (Michael Zehr) writes:
> I often write:
> 
> 	if (something_goes(wrong) )
> 		fprintf(stderr, "%s: I give up!\n", argv[0] ) ,
> 		exit(2) ;
> 
> Of course it's no better than using { ; }, but it's not worse either.

Personally, I think it is worse that {;}. If you have something of the form

	x = Expr1 , Expr2;

then Expr2 will be assigned to x, rather than Expr1. If you rewrite them as

	x = Expr1,
	    Expr2;

you're relying on (a) the indentation and (b) being very careful, to notice you
have a comma instead of a semicolon. Inserting extra code might be nasty:

	x= Expr1,
	   Expr3;
	   Expr2;

*BOOM*...
-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo-oOo
Stephen Kilbane                      |Email: skilbane@uk.co.bt.axion
British Telecom Research Laboratories|or smk-a@uk.ac.york.minster (or, if that
Martlesham Heath                     |doesn't work, root@uk.ac.york.softeng - 
Ipswich IP5 7RE (0473 646638)        |not me, but it may be passed on....
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Disclaimer: Who? Me? Nah - must have been someone else when my back was turned!
Quotes: "If silence is golden, music is platinum"
        "'You haven't lived till you've died in MUD' - I live a lot!"
        "(If platinum is to gold, what is to golden?)"[This space to rent]

robert@arizona.edu (Robert J. Drabek) (08/03/89)

In article <918@helios.toronto.edu>, dooley@helios.toronto.edu (Kevin Dooley) writes:
> 
> Can anybody tell me if there is a usage where the comma is 'better'.
> By this I mean are there any places where using a comma makes the 
> code more readable, efficient, produce cleaner/faster assembler (I
> know this is compiler dependant).  It's just that I've never seen a
> program with the comma operator where I didn't scream and edit it out.

I agree with you.  The one place, though, where it is used is in "for"
loops:  for (i = 0, j = 9; ...; i++, j--)

I have seen the following "attempt" at using a comma operator in a function
call:

       func(expr1, expr2)

The writer thought he was using the comma operator since the function
had been defined as having a single argument.  He did get

       func((expr1, expr2))

to work.  I don't know if all compilers would get this, though.
-- 
Robert J. Drabek
Department of Computer Science
The University of Arizona
Tucson, AZ  85721

SMITHJ@ohstpy.mps.ohio-state.edu (08/04/89)

In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
> ***FLAME ON!***
> Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
> and fprintf(...) and exit(...) ARE valid expressions in C.
> sputter sputter - flame off.

Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
that the *comma* operator ----does not----- guarantee evaluation in any order.
Specifically, the Microsoft 5.0 manual mentions this.

-- 
/* Jeffery G. Smith, BS-RHIT (AKA Doc. Insomnia, WMHD-FM)       *
 *    The Ohio State University, Graduate Physics Program       *
 *        3193 Smith Lab, Columbus, OH 43210  (614) 292-5321    *
 *    smithj@ohstpy.mps.ohio-state.edu                          */

kevin@claris.com (Kevin Watts) (08/04/89)

From article <3287@ohstpy.mps.ohio-state.edu>, by SMITHJ@ohstpy.mps.ohio-state.edu:
> In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
>> ***FLAME ON!***
>> Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
>> and fprintf(...) and exit(...) ARE valid expressions in C.
>> sputter sputter - flame off.
> 
> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> that the *comma* operator ----does not----- guarantee evaluation in any order.
> Specifically, the Microsoft 5.0 manual mentions this.
> 
Hmm, I'll have to check my copy when I get home.  If you're right, it's broken.

I quote from "Standard C", p.88, by P.J. Plauger & Jim Brodie (the secretary
and chairman of X3J11):
	You write X,Y to first evaluate X as a side-effects context
	expression and then to evaluate Y.  There is a sequence point
	between the evaluation of the two operands.

I hope that settles the matter for everyone.  The order IS guaranteed!

This book appears to be an excellent reference for the ANSII C language
definition.  I just got it yesterday.  $7.95 from Microsoft Press.

And now I know the name of the ISO C committee: JTC1 SC22 WG14
Makes X3J11 seem easy to remember, doesn't it?

-- 
 Kevin Watts        ! Any opinions expressed here are my own, and are not
 Claris Corporation ! neccessarily shared by anyone else.  Unless they are
 kevin@claris.com   ! patently absurd, in which case they're not mine either.

craigb@hpqtdla.HP.COM (Craig Bruce) (08/04/89)

  According to my text (Darnell & Margolis's Software Eng. in 'C', p137) :

	"The comma operator is one of the few operators for which the order of
	evaluation is specified. The compiler must evaluate the left-hand
	operator first."

  As this book covers both ANSI standard and K&R and comments on differences
between the two, and since this comment is stated as fact I think it is safe 
to take it as pretty close to gospel.

			Craig


-------------------------------------------------------------------------------
Craig Bruce, 			    \    / .hsif eht lla rof sknaht dna gnol oS
Hewlett-Packard,                     \  / yxalaG eht ot ediuG s'rekcihhctiH -
South Queensferry Telecomms Division. \/ 
-------------------------------------------------------------------------------

wjr@ftp.COM (Bill Rust) (08/04/89)

|From article <3287@ohstpy.mps.ohio-state.edu>, by SMITHJ@ohstpy.mps.ohio-state.edu:
|> In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
||| ***FLAME ON!***
||| Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
|| and fprintf(...) and exit(...) ARE valid expressions in C.
||| sputter sputter - flame off.
|| 
|| Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
|| that the *comma* operator ----does not----- guarantee evaluation in any order.
|| Specifically, the Microsoft 5.0 manual mentions this.
||

Sorry, but you are mistaken. Quoting MSC Language Ref p 130 v5.1 (5.0
is identical), "The sequential-evaluation operator evaluates its two
operands sequentially from left to right. There is a sequence point
after the first operand. The result of the operation has the same
value and type as the right operand. Each operand can be of any type.
 ...  The sequential-evaluation operator, also called the "comma
operator," is typically used to evaluate two or more expressions in
contexts where only one expression is allowed." In short, MS has it
right in their definition and, even though I have lots of experience
with MSC, I find it hard to believe that this point doesn't work
right.

Bill Rust (wjr@ftp.com)

debra@alice.UUCP (Paul De Bra) (08/04/89)

In article <13074@megaron.arizona.edu> robert@arizona.edu (Robert J. Drabek) writes:
}...
}I agree with you.  The one place, though, where it is used is in "for"
}loops:  for (i = 0, j = 9; ...; i++, j--)
}
}I have seen the following "attempt" at using a comma operator in a function
}call:
}
}       func(expr1, expr2)
}
}The writer thought he was using the comma operator since the function
}had been defined as having a single argument.  He did get
>
}       func((expr1, expr2))
}
}to work.  I don't know if all compilers would get this, though.

The following is also a problem:
if i have something like
	if (e)
		return;
and want to get some debug output, i would try
	if (e)
		printf("Hi\n"),return;
but this gives syntax error. (at least in the compilers i've tried)
Note that
	if (e)
		printf("Hi\n"),exit();
compiles fine. It's just that "return" is treated differently.

Paul

-- 
------------------------------------------------------
|debra@research.att.com   | uunet!research!debra     |
------------------------------------------------------

markp@cbnewsd.ATT.COM (mark.j.purdome) (08/04/89)

From article <3287@ohstpy.mps.ohio-state.edu>, by SMITHJ@ohstpy.mps.ohio-state.edu:
> 
> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> that the *comma* operator ----does not----- guarantee evaluation in any order.
> Specifically, the Microsoft 5.0 manual mentions this.
> 
If this is true for MSC 5.0, they fixed it in MSC 5.1.
From MSC 5.1 Language Reference, Section 5.3.11, p. 130:

5.3.11 Sequential-Evaluation Operator

The sequential-evaluation operator evaluates its two operands sequentially
from left to right. ... The sequential-evaluation operator, also called
the "comma operator," is typically used to evaluate two or more expressions
in contexts where only one expression is allowed.

stevenw@oakhill.UUCP (Steven Weintraub) (08/04/89)

In article <10453@claris.com>, kevin@claris.com (Kevin Watts) writes:
> From article <3287@ohstpy.mps.ohio-state.edu>, by SMITHJ@ohstpy.mps.ohio-state.edu:
> > In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
> >> ***FLAME ON!***
> >> Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
> >> and fprintf(...) and exit(...) ARE valid expressions in C.
> >> sputter sputter - flame off.
> > 
> > Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> > that the *comma* operator ----does not----- guarantee evaluation in any order.
> > Specifically, the Microsoft 5.0 manual mentions this.
> > 
> Hmm, I'll have to check my copy when I get home.  If you're right, it's broken.
> 
> I quote from "Standard C", p.88, by P.J. Plauger & Jim Brodie (the secretary
> and chairman of X3J11):
> 	You write X,Y to first evaluate X as a side-effects context
> 	expression and then to evaluate Y.  There is a sequence point
> 	between the evaluation of the two operands.
> 
> I hope that settles the matter for everyone.  The order IS guaranteed!

In fact the standard is even more direct and simpler, to quote (from my
    outdated version - capital THEN mine):

3.3.17 Comma operator

syntax :     expression : assignment-expression
			  expression , assignment-expression

semantics : The left operand of the operator is evaluated as a void expression;
	    there is a sequence point after its evaluation.  THEN the right
	    operand is evaluated;  the result has its type and value.


And now since I have your attention I'll add my two cents on where I place
a comma.  There are two places.  One is the 'for' statement as has been
countlessly mentioned here.  The other is in macro calls, where there is
a posibility a parameter will change in the call.  For example:

#define square(x)   (temp = x,(temp * temp))

(No flames about the example, it is chosen for simplicity).  Now how does
the arguement change.  Try calling it with:

x = 4;
a = square(x++);

With the temp, a = 16 and x = 5: without it a = 20 and x = 5.

Of course you have the overhead of defining the temporary variable in the
program that uses the call.

                   enough from this mooncalf - Steven
----------------------------------------------------------------------------
These opinions aren't necessarily Motorola's or Remora's - but I'd like to
think we share some common views.
----------------------------------------------------------------------------
Steven R Weintraub                             | O Lord,
...!cs.utexas.edu!oakhill!stevenw              |   let me talk gently,
Motorola Inc.  Austin, Texas                   | for I might have to eat my
(512) 891-3023 (office) (512) 453-6953 (home)  |   words tomorrow.
----------------------------------------------------------------------------

smk@dip.eecs.umich.edu (Steve kelley) (08/04/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
>In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
>> Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
>
>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>that the *comma* operator ----does not----- guarantee evaluation in any order.
>Specifically, the Microsoft 5.0 manual mentions this.
>
>/* Jeffery G. Smith, BS-RHIT (AKA Doc. Insomnia, WMHD-FM)       *

I'm afraid you are mistaken.  In particular, the Microsoft C Language
Reference version 5.0 specifically mentions: "The sequential-evaluation
operator evaluates its two operands sequentially from left to right.  There
is a sequence point after the first operand.  The result of the operation 
has the same value and type as the right operand.  Each operand can be of
any type. ... The sequential-evaluation operator, also called the "comma
operator," [sic] is typically used to evaluate two or more expressions
in contexts where only one expression is allowed."

Steve Kelley

mpl@cbnewsl.ATT.COM (michael.p.lindner) (08/04/89)

In article <3287@ohstpy.mps.ohio-state.edu>, SMITHJ@ohstpy.mps.ohio-state.edu writes:
> In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
> > Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
> 
> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> that the *comma* operator ----does not----- guarantee evaluation in any order.
> Specifically, the Microsoft 5.0 manual mentions this.
> 
> /* Jeffery G. Smith, BS-RHIT (AKA Doc. Insomnia, WMHD-FM)       *

Then
	a) you haven't read K&R (original or second edition)
	b) you haven't read the ANSI standard

since these all state specifically that the comma operator evaluates left
to right.

corollary
	MSC 5.0 doesn't follow either K&R or ANSI C standard

I stand by my original statement.

Mike Lindner
attunix!mpl
AT&T Bell Laboratories
190 River Rd.
Summit, NJ 07901

Tim_CDC_Roberts@cup.portal.com (08/04/89)

Steve Kilbane writes:
>
>    x1 = expr1,          x1 = expr1,
>         expr2;   ==>         expr3;
>                              expr2;

Oooooh, that is a nasty one.  It's that kind of "but_I_only_changed_one_line"
modification that gives professional maintainers ulcers.

I consider that a very good argument against the comma operator.

Tim_CDC_Roberts@cup.portal.com                | Control Data...
...!sun!portal!cup.portal.com!tim_cdc_roberts |   ...or it will control you.

karl@haddock.ima.isc.com (Karl Heuer) (08/04/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>that the *comma* operator ----does not----- guarantee evaluation in any order.
>Specifically, the Microsoft 5.0 manual mentions this.

You're mistaken.  Probably you're thinking of the comma *punctuator*, e.g. the
thing used in function calls.  Function arguments can be (and are) evaluated
in an unspecified order, but this has nothing to do with the comma operator.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (08/04/89)

In article <2550097@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>Another convenient use of the comma operator is in for loops ...

Which is only necessary because of a flaw in the language, in that it requires
the pieces of a "for" statement to be expressions rather than statements, even
though the values of the first and third pieces are ignored.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/04/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>that the *comma* operator ----does not----- guarantee evaluation in any order.
>Specifically, the Microsoft 5.0 manual mentions this.

Are you sure you're not confusing the comma separating two function
arguments with the comma operator?  The comma operator has ALWAYS
been defined to evaluate its LHS before its RHS.  If the MicroSoft
5.0 manual claims otherwise, then either it's wrong or they're
trying to cover up a SEVERE bug in their compiler!

bph@buengc.BU.EDU (Blair P. Houghton) (08/05/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
>
>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>that the *comma* operator ----does not----- guarantee evaluation in any order.
>Specifically, the Microsoft 5.0 manual mentions this.

HAHAHAHEEHEEEHOHOHOHOHAHAHEEEEEEhaaaawheheheeeehoohohohohaha

Whinny!  Laughed myself horse on that one.

You're probably not mistaken, though; I don't doubt a bit that a
Microsoft compiler for any language would implement it in such a way as
to controvert every tenet of the language's original specifications.
I've been pounding on the Pascal compiler for a couple of weeks,
discovering literally dozens of such misfeaturings.  All this and
it's to control a store-bought data-acquisition board and DSP processor,
so any bug appears as if magnified by a 100-inch telescope.

My point, here, is that it is folly to either:  a) Use a Microsoft
product as a standard for anything other than microsoft products; or
b) Trust portability in any form for any feature of a compiler that
isn't nailed down by ANSI, and for C that's a null set, as yet.

Order of evaluation for the comma operator may well be un-guaranteed,
and therefore unportable.

Caveat programmator.

				--Blair
				  "Perhaps I could interest you
				   in a few sums of pointers?"

bph@buengc.BU.EDU (Blair P. Houghton) (08/05/89)

In article <2135@zaphod.axion.bt.co.uk> skilbane@zaphod.axion.bt.co.uk writes:
>From article <2963@solo6.cs.vu.nl>, by roemer@cs.vu.nl (Roemer Lievaart):
>> tada@athena.mit.edu (Michael Zehr) writes:
>
>Personally, I think it is worse that {;}. If you have something of the form
>
>	x = Expr1 , Expr2;
>
>then Expr2 will be assigned to x, rather than Expr1. If you rewrite them as

No.  For precedence, the comma operator is the lowest of the low.

Checking the table on p. 18 of Andrew Koenig's _C_Traps_and_Pitfalls_
(I'd have looked in K&RI, but Andy's book was closer).

One sees that the bottom three, in decreasing order, are

	?:
	assignments
	,

so in the example above, x would be assigned Expr1, and the statement
would "return" the value of Expr2, esentially returning it nowhere,
the implications of which are moot, and were discussed here sometime
around January.  E.g.,

	x = a ? b : c , a ? c : b ;

As far as x is concerned, this reads as

	if ( a != 0 )
	    x = b;
	else
	    x = c;

				--Blair
				  " what ? me : worry ; "  

ark@alice.UUCP (Andrew Koenig) (08/05/89)

In article <3287@ohstpy.mps.ohio-state.edu>, SMITHJ@ohstpy.mps.ohio-state.edu writes:

> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> that the *comma* operator ----does not----- guarantee evaluation in any order.
> Specifically, the Microsoft 5.0 manual mentions this.

You're mistaken.

K&R, second edition, page 209:

	A pair of expressions separated by a comma is evaluated
	left-to-right, and the value of the left expression is
	discarded.  The type and value of the result are the type
	and value of the right operand.  All side effects from the
	evaluation of the left operand are completed before
	beginning evaluation of the right operand.

Perhaps you should check your Microsoft manual again; if it really
says that evaluation order of comma is undefined, I suggest a letter
to Microsoft [and hope their compiler doesn't get it wrong too!]
-- 
				--Andrew Koenig
				  ark@europa.att.com

hascall@atanasoff.cs.iastate.edu (John Hascall) (08/05/89)

In article <9736> debra@alice.UUCP () writes:
}In article <13074> robert@arizona.edu (Robert J. Drabek) writes:
  
     [... comma stuff ...]

}The following is also a problem:
}if i have something like
}	if (e)
}		return;
}and want to get some debug output, i would try
}	if (e)
}		printf("Hi\n"),return;
}but this gives syntax error. (at least in the compilers i've tried)
}Note that
}	if (e)
}		printf("Hi\n"),exit();
}compiles fine. It's just that "return" is treated differently.


     Return is "treated differently" because it is a statement,
     not an expression--exit being a function is an expression.

     (wouldn't it be even more obfuscating and fun is all C
     statements were also expressions!! [holy shades of BLISS])


     I use something like this for that reason:

     #define GAG(msg,cond)   return(printf("...%s\n", msg), cond)

     if (e) GAG("Why the devil is `e' true?", ERR_ETRUE);


John Hascall
ISU Comp Center
Ames IA

karzes@mfci.UUCP (Tom Karzes) (08/05/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>that the *comma* operator ----does not----- guarantee evaluation in any order.
>Specifically, the Microsoft 5.0 manual mentions this.

I find that difficult to believe.  You're probably confusing the comma
operator with the comma argument list separator.  The former guarantees
left-to-right evaluation in any implementation which has any business
calling itself C.  The latter does not guarantee any order of evaluation.

See section 7.15 of the original C reference manual, section 7.15 of the
C++ reference manual, and section A7.18 of the new C reference manual (in
the latest edition of K&R).  These sections clearly explain the left-to-right
semantics of the comma operator, and conclude with the following example:

    f(a, (t=3, t+2), c)

It states that this [function reference] has three arguments, the second
of which has the value 5.

Similarly, ANSI C describes the comma operator as having a sequence point
after the evaluation of the left operand, and concludes with the IDENTICAL
example shown above (this is in section 3.3.17 of the copy of the draft
I'm looking at).

As I said, you've almost certainly confused the comma operator with the
comma argument list separator.  I don't believe the Microsoft people
would have been stupid enough not to support the comma operator correctly
(if they really were that stupid, then they should call their language C--,
because it certainly isn't C).

ark@alice.UUCP (Andrew Koenig) (08/05/89)

In article <2135@zaphod.axion.bt.co.uk>, skilbane@zaphod.axion.bt.co.uk (Steven Kilbane) writes:

> Personally, I think it is worse that {;}. If you have something of the form

> 	x = Expr1 , Expr2;

> then Expr2 will be assigned to x, rather than Expr1.

Nope.  = binds more tightly than , so

	x = Expr1 , Expr2;

means the same as

	(x = Expr1) , Expr2;
-- 
				--Andrew Koenig
				  ark@europa.att.com

news@cs.Helsinki.FI (news) (08/05/89)

From: grano@kreeta.cs.Helsinki.FI (Juhani Grano)
Path: kreeta!grano

"The sequential evaluation operator evaluates its two operands sequentially
from left to right. There is a sequence point after the first operand."

	Maybe MSC 5.0 is not standard-conforming in this respect.
Kari.
------------------------------
Kari Grano				University of Helsinki, Finland
email to: grano@cs.helsinki.fi		Department of CS
	"I have a thousand telephones that don't ring"

roemer@cs.vu.nl (Roemer Lievaart) (08/05/89)

I wrote:

>> I often write:
>> 
>> 	if (something_goes(wrong) )
>> 		fprintf(stderr, "%s: I give up!\n", argv[0] ) ,
>> 		exit(2) ;
>> 
>> Of course it's no better than using { ; }, but it's not worse either.

skilbane@zaphod.axion.bt.co.uk (Steven Kilbane) wrote

>Personally, I think it is worse that {;}. If you have something of the form
>	x = Expr1 , Expr2;
>then Expr2 will be assigned to x, rather than Expr1. If you rewrite them as
>	x = Expr1,
>	    Expr2;
>you're relying on (a) the indentation and (b) being very careful, to notice you
>have a comma instead of a semicolon. Inserting extra code might be nasty:
>	x= Expr1,
>	   Expr3;
>	   Expr2;

>*BOOM*...

What BOOM?
I gave a very specific example of where I use the comma-operator, where
it is not better or worse than using { ; }.

You come up with very, very different examples. Situations where I maybe would
never dream of using the comma operator. I never said I always use the comma
operator instead of { ; }, did I?
Sorry, but this is no reason for you to say "BOOM"! :-)

*BOOM* yourself.... ;-)

Regards,
	Roemer.
____________________________________________________________________________
Roemer B. Lievaart | "We would have killed him totally, were it not that an
Amsterdam, Holland | unexplicable fear made our heart stink into our boots
Europe, Earth.     | and we slunk off, and so I stand before you... How well
roemer@cs.vu.nl    | put, but nobody listens..."  -- Alfred Jarry's "Ubu Roi"

Or, to quote somenody (dunno who anymore):
I like the comma operator. I seldom use it, but I like it.

tneff@bfmny0.UUCP (Tom Neff) (08/05/89)

Hope I'm not repeating, but Harbison & Steele II (p.187) say:

  "The comma operator guarantees that its operands will be evaluated
in left-to-right order, but other uses of the comma character do not
make this guarantee.  For example, the argument expressions in a
function invocation need not be evaluated in left-to-right order."

-- 
"We walked on the moon --	((	Tom Neff
	you be polite"		 )) 	tneff@bfmny0.UU.NET

michael.p.lindner@mamab.FIDONET.ORG (michael.p.lindner) (08/05/89)

--  
Fidonet:  michael.p.lindner via 1:363/9
Internet: michael.p.lindner@mamab.FIDONET.ORG
Usenet:  ...!peora!rtmvax!libcmp!mamab!michael.p.lindner

spl@mcnc.org (Steve Lamont) (08/05/89)

In article <5418@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>Herewith the only use for the comma operator outside a macro that I can
>think of:
>
>	for(init1, init2; test; incr1, incr2)...

Can anyone tell me whether order of evaluation is guaranteed in this context?
I seem to remember either of running afoul of some order of evaluation bogon or reading somewhere that order of evaluation was not guaranteed... or maybe I'm
thinking of function calls (???).

Email replies will suffice unless someone has something earth-shattering to
add.

-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

bph@buengc.BU.EDU (Blair P. Houghton) (08/06/89)

In article <9736@alice.UUCP> debra@alice.UUCP () writes:
>
>	if (e)
>		printf("Hi\n"),return;
>
>gives syntax error. (at least in the compilers i've tried)
>
>	if (e)
>		printf("Hi\n"),exit();
>
>compiles fine. It's just that "return" is treated differently.

BECAUSE IT'S A STATEMENT!!

Pardon the tone, but this is actually a joke I'm telling, here...
Several of you will get it.  Go to the next article while I explain...


The original examples in this subject thread used

	fprintf(...) , exit(0) ;

and I made the mistake of thinking these were statements and I flamed
on that point and I was soundly thrashed for my misstatements.

The return statement, however, is just that, a statement.  The things
on either side of a comma opertor must be expressions.  The element
formed by expressions and comma operators is itself an expression.
You can't stick for-loops in a comma-expression, for example.

The syntax summary at the back of K&R is probably the best place
to find a concise definition of the distinction between expressions
and statements

				--Blair
				  "Vindication is satisfying,
				   which is also an expression."

dts@quad.uucp (David T. Sandberg) (08/06/89)

In article <3611@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
:In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
:>Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
:>that the *comma* operator ----does not----- guarantee evaluation in any order.
:>Specifically, the Microsoft 5.0 manual mentions this.
:
:HAHAHAHEEHEEEHOHOHOHOHAHAHEEEEEEhaaaawheheheeeehoohohohohaha
:
:Whinny!  Laughed myself horse on that one.
:
:You're probably not mistaken, though; I don't doubt a bit that a
:Microsoft compiler for any language would implement it in such a way as
:to controvert every tenet of the language's original specifications.

Come on, give Microsoft a break here.  At least one article has
appeared which sets the record straight on this; MSC treats the
comma operator in the correct manner (left to right order of
evaluation), and the person above was wholly mistaken.  Please:
Microsoft gets quite enough grief for their real problems; it's
pointless to badrap them for bugs that *don't* exist.

-- 
                                  David Sandberg
 "bidibidibidibidi... here's      PSEUDO: dts@quad.uucp
      your flower, Buck"          ACTUAL: ..uunet!rosevax!sialis!quad!dts

stephenf@softway.oz (Stephen Frede) (08/06/89)

> Can anybody tell me if there is a usage where the comma is 'better'.

Just to add another example to the fray

	while
	(
	    printf("enter a number: "), 
	    scanf("%f", &num) == 1
	)
	{
	    ...	/* calculations on num */
	}

			Regards,

				- Stephen Frede

Softway Pty Ltd, P.O. Box 305, Strawberry Hills, NSW 2012, AUSTRALIA
Phone: +61 2 698 2322; Fax: +61 2 699 9174; Telex: AA27987
ACSnet: stephenf@softway.oz	UUCP: ...!uunet!softway.oz!stephenf

Steven.Kilbane@mamab.FIDONET.ORG (Steven Kilbane) (08/06/89)

--  
Fidonet:  Steven Kilbane via 1:363/9
Internet: Steven.Kilbane@mamab.FIDONET.ORG
Usenet:  ...!peora!rtmvax!libcmp!mamab!Steven.Kilbane

tps@chem.ucsd.edu (Tom Stockfisch) (08/06/89)

In article <1351@cbnewsl.ATT.COM> mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
>> > >		fprintf(stderr, "Can't open %s\n", file), exit(2);

>Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
>and fprintf(...) and exit(...) ARE valid expressions in C.

This is valid dpANS code, but it is not currently portable.

Many C compilers do not allow void operands of comma operators.
Many libraries also declare exit() to return void.
Systems that do both will not accept the above statement.
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

campbell@redsox.bsw.com (Larry Campbell) (08/07/89)

In article <3287@ohstpy.mps.ohio-state.edu> SMITHJ@ohstpy.mps.ohio-state.edu writes:
-
-Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
-that the *comma* operator ----does not----- guarantee evaluation in any order.
-Specifically, the Microsoft 5.0 manual mentions this.

You are mistaken, and if you're quoting Microsoft accurately, they're
mistaken too.  I quote from The Bible (edition 1, ss. 7.15, pg. 192):

	A pair of expressions separated by a comma is evaluated
	left-to-right and the value of the left expression is
	discarded.

-- 
Larry Campbell                          The Boston Software Works, Inc.
campbell@bsw.com                        120 Fulton Street
wjh12!redsox!campbell                   Boston, MA 02146

rosenkra@hall.cray.com (Bill Rosenkranz) (08/07/89)

---
can we end this discussion already? RTFM!!! enough is enough...(sheesh)

-bill
rosenkra@boston.cray.com

peter@ficc.uu.net (Peter da Silva) (08/07/89)

In article <1938@softway.oz>, stephenf@softway.oz (Stephen Frede) writes:
> 	while ( printf("enter a number: "), scanf("%f", &num) == 1 )
> 	    ...	/* calculations on num */

Only because C doesn't have a general looping construct. I once
suggested this syntax:

	[do
		statement]
	[while(expr)
		statement]

Which includes both standard do...while, and while. Unfortunately it's
also even more susceptible to typos than regular do...whiles, so I got
roundly rejected.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: peter@ficc.uu.net, +1 713 274 5180. | "The sentence I am now
Personal: peter@sugar.hackercorp.com.   `-_-' |  writing is the sentence
Quote: Have you hugged your wolf today?  'U`  |  you are now reading"

dg@lakart.UUCP (David Goodenough) (08/08/89)

From article <3287@ohstpy.mps.ohio-state.edu>, by SMITHJ@ohstpy.mps.ohio-state.edu:
> In article <1351@cbnewsl.ATT.COM>, mpl@cbnewsl.ATT.COM (michael.p.lindner) writes:
>> ***FLAME ON!***
>> Sigh.  RTFM!  The comma operator guarantees left to right evaluation,
>> and fprintf(...) and exit(...) ARE valid expressions in C.
>> sputter sputter - flame off.
> 
> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
> that the *comma* operator ----does not----- guarantee evaluation in any order.
> Specifically, the Microsoft 5.0 manual mentions this.

In that case, MS C 5.0 is broken.

if I say:

	int a;

	a = (blurfl(), stug(), zorch());

and get _ANY_ other order of evaluation than blurfl() first, then stug(),
and finally zorch(), then I'm gonna deep six that compiler. The confusion
_MAY_ be arising due to the overloading of the comma operator: as a separator
in expressions it _DOES_ guarantee l->r order of eval, when separating
arguments to a function - as in:

	a = zap ( blurfl(), stug(), zorch() );

it definitely guarantees _NOTHING_.
-- 
	dg@lakart.UUCP - David Goodenough		+---+
						IHS	| +-+-+
	....... !harvard!xait!lakart!dg			+-+-+ |
AKA:	dg%lakart.uucp@xait.xerox.com		  	  +---+

gregw@otc.otca.oz (Greg Wilkins) (08/10/89)

In article <1296@atanasoff.cs.iastate.edu>, hascall@atanasoff.cs.iastate.edu (John Hascall) writes:

>      (wouldn't it be even more obfuscating and fun is all C
>      statements were also expressions!! [holy shades of BLISS])
> 

If all C statements were suddenly redefined as void expression, what difference
would it make to the language?

It would add some flexibility and orthogonality, but would it stop any
existing programs from compiling?

I cant see it causing a problem unless it caused ambiguities in the grammar?


-Greg Wilkins

kdb@chinet.chi.il.us (Karl Botts) (08/10/89)

>> Maybe I'm mistaken, but I'm sure that all the documentation I've read warns
>> that the *comma* operator ----does not----- guarantee evaluation in any order.
>> Specifically, the Microsoft 5.0 manual mentions this.
>> 
>If this is true for MSC 5.0, they fixed it in MSC 5.1.

It was never true, certainly not for any Microsoft compiler since 4.0, and
not for any compiler I ever heard of (there have bben some that did not
support the comma operator at all).  

I think there are legitimate places for the comma operator outside macro
expnsions and loop control statements.  YOu just have to remember that it
has the lowest precedence of any operator, and thus must be protected with
perens.

Using the comma operator can emphasize that several statements are
logically atomic -- that together, they are doing something which may be
though of as asingle operation.  for instance:

i += x, j -=x;
if ( i >= j )
	...

I grant that the semi-colon can always be used in these cases, but I see no
harm in the comma operator.

I have also written code something like this:

linked_list_node_t *p;
if ( p && ( p = p->next, p ) )
	/* something */


No doubt there are other ways to do it, but I don't see this as a sin.

ccel@chance.uucp (CCEL) (08/12/89)

>I have also written code something like this:
>
>linked_list_node_t *p;
>if ( p && ( p = p->next, p ) )
>	/* something */

I've never seen this format, how does exactly does this work?

>No doubt there are other ways to do it, but I don't see this as a sin.

Wouldn't this produce the same result:

if (p && ( p = p->next ) )

??
Randy Tidd                   MITRE-McLean CCEL Lab
rtidd@mitre.arpa             ccel%community-chest@gateway.mitre.org
#define DISCLAIM TRUE

stevenw@oakhill.UUCP (Steven Weintraub) (08/14/89)

After careful thought I have found another place I use the comma operator.

It is in a while statement when I am reading a line.  I use:

while ((ch = getchar()), ch != EOF && ch != '\n')

Although I have never been quite satisfied with this, I have never found
a structure that does this which I find more satisfying.  Any comments
from the peanut gallery?

                   enough from this mooncalf - Steven
----------------------------------------------------------------------------
These opinions aren't necessarily Motorola's or Remora's - but I'd like to
think we share some common views.
----------------------------------------------------------------------------
Steven R Weintraub                             | O Lord,
...!cs.utexas.edu!oakhill!stevenw              |   let me talk gently,
Motorola Inc.  Austin, Texas                   | for I might have to eat my
(512) 891-3023 (office) (512) 453-6953 (home)  |   words tomorrow.
----------------------------------------------------------------------------

arrom@aplcen.apl.jhu.edu (Ken Arromdee) (08/15/89)

>while ((ch = getchar()), ch != EOF && ch != '\n')
>Although I have never been quite satisfied with this, I have never found
>a structure that does this which I find more satisfying.  Any comments
>from the peanut gallery?

while ((ch = getchar()) != EOF && ch != '\n')
--
"The fact is self evident from the text and requires no supporting argument."
  --Tim Maroney

Kenneth Arromdee (UUCP: ....!jhunix!ins_akaa; BITNET: g49i0188@jhuvm;
     INTERNET: arromdee@crabcake.cs.jhu.edu) (please, no mail to arrom@aplcen)

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/15/89)

In article <2300@oakhill.UUCP> stevenw@oakhill.UUCP (Steven Weintraub) writes:
>while ((ch = getchar()), ch != EOF && ch != '\n')
>Although I have never been quite satisfied with this, I have never found
>a structure that does this which I find more satisfying.

The usual idiom is

	while ( (ch = getchar()) != EOF && ch != '\n' )

ark@alice.UUCP (Andrew Koenig) (08/15/89)

In article <2300@oakhill.UUCP>, stevenw@oakhill.UUCP (Steven Weintraub) writes:

> while ((ch = getchar()), ch != EOF && ch != '\n')

I don't see any obvious reason that this is better than

	while ((ch = getchar()) != EOF && ch != '\n')

Do you?
-- 
				--Andrew Koenig
				  ark@europa.att.com

stevenw@oakhill.UUCP (Steven Weintraub) (08/15/89)

Before I go on, I would like to thank everyone who has responded so
far (both publically and email).  But now to the question.

In article <9775@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
> In article <2300@oakhill.UUCP>, stevenw@oakhill.UUCP (Steven Weintraub) writes:
> 
> > while ((ch = getchar()), ch != EOF && ch != '\n')
> 
> I don't see any obvious reason that this is better than
> 
> 	while ((ch = getchar()) != EOF && ch != '\n')

Let me turn this around.  I have considered using this form before
and find it less satisfying than the original I posted.  It should
be pointed out that in both cases the code generated is the same,
so there is no gain or loss with either method.  I personally still
prefer my form better.  I think it is clearer that two functions are
happening here (assigning ch and testing against the exit condition).
And while I hate to disagree with the likes of Doug Gwyn and Kenneth
Arromdee, I believe I will still stick with my earlier form.

Now to dispense with some forms sent to me by email:

2 people sent me :
    
    for (ch = getchar();ch != EOF && ch != '\n';ch = getchar())

This is not preferred for the simple reason it will generate the
getchar twice.  If, as is often the case in the real word, you
are using another routine or macro to fetch the characters (not
one of the system macros) this can cause a lot of overhead.

As for the comment that the parenthesis around the ch = getchar() are 
not necessary.  This I know.  But I was raised to believe that an
extra amount of caution (especially in matters of precedence) is never
wasted.  If it doesn't generate extra code or confuse the programmer,
I usually put them in.

                   enough from this mooncalf - Steven
----------------------------------------------------------------------------
These opinions aren't necessarily Motorola's or Remora's - but I'd like to
think we share some common views.
----------------------------------------------------------------------------
Steven R Weintraub                             | O Lord,
...!cs.utexas.edu!oakhill!stevenw              |   let me talk gently,
Motorola Inc.  Austin, Texas                   | for I might have to eat my
(512) 891-3023 (office) (512) 453-6953 (home)  |   words tomorrow.
----------------------------------------------------------------------------

paulr@sequent.UUCP (Paul Reger) (08/18/89)

Considering the construction:

while ((ch = getchar()) != EOF && ch != '\n')

Is there any assurance in any C standard that the left expression will
always be evaluated first, with the right following it ??  I mean for
purposes of optimization, the right should be evaluated first, unless
there is something in some standard somewhere limiting such
optimizations...

I'm from Ada-land where such problems are handled by the 'and then'
clause.

Anybody know ???

chad@csd4.csd.uwm.edu (D. Chadwick Gibbons) (08/19/89)

In article <20348@sequent.UUCP> paulr@crg3.UUCP (Paul Reger) writes:
|Considering the construction:
|
|while ((ch = getchar()) != EOF && ch != '\n')
|
|Is there any assurance in any C standard that the left expression will
|always be evaluated first, with the right following it ??

	It's mentioned in K&R, and most likely the standard; many C programs
rely on the property of boolean evaluation: left to right.  If the first
expression ((ch = getchar()) != EOF is false, there is no need to complete the
second comparison, so the compare falls through.  This is a reliable C
operation.
--
D. Chadwick Gibbons - chad@csd4.csd.uwm.edu

volpe@underdog.crd.ge.com (Christopher R Volpe) (08/09/90)

Thanks to all who pointed out to me that the comma operator
does not return an lvalue in the Standard, bug GNU C provides this
as an extension.

Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com