[comp.lang.c] Not only that, but...

mwm@eris.BERKELEY.EDU (Mike (Don't have strength to leave) Meyer) (11/12/86)

In article <166@houligan.UUCP> dave@murphy.UUCP (H. Munster) writes:
>In article <630@dg_rtp.UUCP>, throopw@dg_rtp.UUCP (Wayne Throop) types:
>>Again folks, play it safe: *NEVER* have two side-effects on a single
>>object in a single expression.
>
>Not only that, but: don't even *USE* an assigned-to object anywhere else
>in the expression!

The first isn't quite sufficient, as Dave showed. But the second is an
over-reaction.  There are operators in C that are guaranteed to
preserve order, so you can make an assignment then use the variable
assigned to.

To wit, '||' and '&&' WILL be evaluated left-to-right (and short
circuit), so you can safely write:

	while ((c = getchar()) != TERMINATOR && c != EOF)
		;

Since leaving off the test for EOF is usually a bug, this is a
good thing. I know, this example can be rewritten as a do-while, and
you can move subsequent tests to the top of the loop with breaks. But
the first case isn't always true, and the second isn't as readable as
the above C idiom.

	<mike

dave@murphy.UUCP (Rael's brother John) (11/27/86)

In article <1638@jade.BERKELEY.EDU>, mwm@eris.BERKELEY.EDU (Mike (Don't have 
strength to leave) Meyer) writes:

[person quoted is me]
>>Not only that, but: don't even *USE* an assigned-to object anywhere else
>>in the expression!
>
>There are operators in C that are guaranteed to
>preserve order, so you can make an assignment then use the variable
>assigned to.
>
>To wit, '||' and '&&' WILL be evaluated left-to-right (and short
>circuit), so you can safely write:
>
>	while ((c = getchar()) != TERMINATOR && c != EOF)
>		;

You're right.  Just to prove that I'm not dogmatic about it, I will reveal
an idiom of my own the violates my own assertion (the side effect involved
here is a function call rather than an assignment, but the principle is
the same):

       while ( (fgets(buffer,sizeof(buffer),foo) , !feof(foo) )
       {
              <stuff>
       }

I've found this to be a convenient way of setting up a loop to read lines
of text from and process them.  The test is clearly visible in the "while"
statement, no test-and-break within the loop is needed, and no "pump-priming"
read before the start of the loop is necessary.  This works because the
statement that you made about the && and || operators is also true of the
comma operator.  I think that where the person who posted the original
j = (k=1,k) + (k=2,k) business went wrong was in assuming that the
characteristics of the comma operator would apply globally across the +
operator, which of course isn't true of *any* operator in C.

I can think of one other case that seems like it should work, although I can't
prove it:

	j = ( (k=func())>0 ? k : 0)

The intent is that func is called and assigned to k, and then the value
assigned to j is either the value of k if k>0, or 0 if k<=0.  This seems
that it should be OK, because K&R states that for the question-mark
operator, only one of the second and third operands is evaluated, and
it seems to me that the first operand would first have to be fully evaluated in
order to determine which of the other two to evaluate.  But I can't find
any place where it comes right out and says this.

P.S.: how come there's no ^^ operator?
---
"I used to be able to sing the blues, but now I have too much money."
-- Bruce Dickinson

Dave Cornutt, Gould Computer Systems, Ft. Lauderdale, FL
UUCP:  ...!{sun,pur-ee,brl-bmd,bcopen}!gould!dcornutt
 or ...!{ucf-cs,allegra,codas}!novavax!houligan!dcornutt
ARPA: dcornutt@gswd-vms.arpa (I'm not sure how well this works)

"The opinions expressed herein are not necessarily those of my employer,
not necessarily mine, and probably not necessary."

greg@utcsri.UUCP (Gregory Smith) (11/29/86)

In article <18@houligan.UUCP> dave@murphy.UUCP (Rael's brother John) writes:
[ in another article he writes ...]
>>>Not only that, but: don't even *USE* an assigned-to object anywhere else
>>>in the expression!

well, that's it for 'i=i+1;', i guess.....	:-)
Somebody else:
>>
>>There are operators in C that are guaranteed to
>>preserve order, so you can make an assignment then use the variable
>>assigned to.
... stuff about &&, ||, ',' etc.

>You're right.  Just to prove that I'm not dogmatic about it, I will reveal
>an idiom of my own the violates my own assertion (the side effect involved
>here is a function call rather than an assignment, but the principle is
>the same):
>
>       while ( (fgets(buffer,sizeof(buffer),foo) , !feof(foo) )
...
>I can think of one other case that seems like it should work, although I can't
>prove it:
>
>	j = ( (k=func())>0 ? k : 0)
>
>The intent is that func is called and assigned to k, and then the value
>assigned to j is either the value of k if k>0, or 0 if k<=0.  This seems
>that it should be OK, because K&R states that for the question-mark
>operator, only one of the second and third operands is evaluated, and
>it seems to me that the first operand would first have to be fully evaluated in
>order to determine which of the other two to evaluate.  But I can't find
>any place where it comes right out and says this.

I think you just proved it.
Both of these are guaranteed to work as you say. It's not as simple
and restrictive as saying "you can't use an assigned to object anywhere
else in the expression", but it's not all that complicated, either.
-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

ark@alice.UUCP (11/30/86)

In article <18@houligan.UUCP>, dave@murphy.UUCP writes:
> P.S.: how come there's no ^^ operator?

Because in order to determine the value of a^b, you must
always evaluate both a and b.