[comp.lang.c] Evaluation of if's

fpb@ittc.wec.com (Frank P. Bresz) (06/05/91)

This is a post for a friend:

Direct replies to fpb@ittc.wec.com because I am interested and
perkins@cgi.com, he can't post/read news but he can get mail.

I will capture the thread and mail to him if you think this seems to have
enough interest to post back instead of mailing.

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

So what do you think of the following:

main()
{
	int i;

	if ( (i=1) == (i=2) )
	{
		printf( "i'm an ultrix compiler\n" );
	}
	else
	{
		printf( "i'm a sun compiler\n" );
	}
}

Is somebody wrong or is the behavior undefined?  I didn't look at the
sun assembly code, but on the ultrix the comparison seems to have been
optimized away (even with the optimizer off).  Ultrix seems to say
"hey, contents of i equal contents of i so why bother?"  Sun seems happy
to compare the results of 2 different expressions even though the results
are stored in the same place.

					don.

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

Here is my personal opinion along with some more information about various
vendors C Compilers.

Personal opinion: I think the behaviour is undefined by K&R anyway I can't
say for ANSI.

VAX C version 3.1 behaves as though it were ultrix.

Here are some results on the machines I have access to, just a few flavors
of C compilers, I won't dignify the question by trying a PC :

On Ultrix 4.1 running on a DECStation 5000/200

$ cd src
$ cc -o dontest dontest.c
$ dontest
i'm an ultrix compiler
$ cc -O4 -o dontest dontest.c
$ dontest
i'm an ultrix compiler
$

Now a Sun3 runnning StunOS 4.1 :

fpb@ip2_ins1:src 3==>make dontest
cc -g   -target sun3 -o dontest dontest.c
fpb@ip2_ins1:src 4==>dontest
i'm a sun compiler

OK It knows it's a Sun how about if we optimize

fpb@ip2_ins1:src 5==>cc -O  -target sun3 -o dontest dontest.c
fpb@ip2_ins1:src 6==>dontest
i'm an ultrix compiler

Ahh now it thinks its ultrix.

Now a Sun4  runnning StunOS 4.1 :

fpb@ittc:src 112==>cc   -target sun4 -o dontest dontest.c
fpb@ittc:src 113==>dontest
i'm a sun compiler
fpb@ittc:src 114==>cc -O   -target sun4 -o dontest dontest.c
fpb@ittc:src 115==>dontest
i'm an ultrix compiler

Seems to work just like the sun3 no surprise there.

Now lets try the Sun386i running StunOS 4.0.2 :

fpb@doccent:src 12==>cc -g   -sun386 -o dontest dontest.c
fpb@doccent:src 13==>dontest
i'm a sun compiler

OK optimize

fpb@doccent:src 14==>cc -O  -sun386 -o dontest dontest.c
fpb@doccent:src 15==>dontest
i'm a sun compiler

Hmmm still Sun, Optimize some more

fpb@doccent:src 16==>cc -O3  -sun386 -o dontest dontest.c
fpb@doccent:src 17==>dontest
i'm a sun compiler

Still Sun, Go all the way

fpb@doccent:src 18==>cc -O9  -sun386 -o dontest dontest.c
cc: Illegal optimization option "-O9"

Shoot! OK how about 5
fpb@doccent:src 19==>cc -O5  -sun386 -o dontest dontest.c
cc: Illegal optimization option "-O5"

Allright 4
fpb@doccent:src 20==>cc -O4  -sun386 -o dontest dontest.c
fpb@doccent:src 21==>dontest
i'm a sun compiler

Still no dice (Oh well noone ever said the 386i had intelligence)

Now lets see how the mighty VAX 6530 running VMS 5.4 and using VAX C 3.1
does on this. 

fpb@kklvx1==>cc dontest.c
fpb@kklvx1==>link dontest,sys$library:vaxcrtl/lib
fpb@kklvx1==>run dontest
i'm an ultrix compiler

Hmmmm, perhaps that message should read I am on some sort of DEC machine that
likes to optimize easy stuff no matter what.

Anyway what do the gods think?
--
| ()  ()  () | Frank P. Bresz   | Westinghouse Electric Corporation
|  \  /\  /  | fpb@ittc.wec.com | ITTC Simulators Department
|   \/  \/   | uunet!ittc!fpb   | Those who can, do. Those who can't, simulate.
| ---------- | +1 412 733 6749  | My opinions are mine, WEC doesn't want 'em.

scs@adam.mit.edu (Steve Summit) (06/05/91)

In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com (Frank P. Bresz) writes:
>	if ( (i=1) == (i=2) )
>
>Is somebody wrong or is the behavior undefined?
>Personal opinion: I think the behaviour is undefined by K&R anyway I can't
>say for ANSI.

Of course it's undefined.  (It contains two side effects not
separated by a sequence point.)  Given that the behavior is
undefined, I'd say it's fairly pointless to catalog the behavior
of available compilers.  As Kernighan and Ritchie point out, and
I am fond of quoting, "if you don't know how they are done on
various machines, that innocence may help to protect you."

The comp.lang.c frequently-asked questions list has a bit to say
about undefined order of evaluation.  Did you check it first?

                                            Steve Summit
                                            scs@adam.mit.edu

bard@cutter.ssd.loral.com (J H Woodyatt) (06/05/91)

In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu (Steve Summit) writes:
|> In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com (Frank P. Bresz) writes:
|> >	if ( (i=1) == (i=2) )
|> >
|> >Is somebody wrong or is the behavior undefined?
|> >Personal opinion: I think the behaviour is undefined by K&R anyway I can't
|> >say for ANSI.
|> 
|> Of course it's undefined.  (It contains two side effects not
|> separated by a sequence point.)

Is this really undefined by ANSI? I suppose we need someone with the STANDARD to
resolve this. (I'm politely assuming that there is a good reason for wanting to
though I'm unable to think of one.)

My 2nd edition K&R book says in the glossary (p.208) that the result of an
assignment expression is the value that was stored in the lvalue after the
assignment takes place. Thus, independent of order of evaluation, the above
expression should always evaluate FALSE. (Or at least so say I.)

The fact that *my* compiler seems to overlook this wording is somewhat alarming
to me. I'd like to know what *else* it's willing to ignore, mangle or optimize
into oblivion incorrectly.

Which leads to an interesting question about portable programming. What fringy
kinds of things in a standard can one expect compilers to sometimes overlook and
thus be classifiable in the category of `Bad Programming Practice.'

 __________________________________________________________________
|
| James Woodyatt                 VOICE:  (415) 852-5429
| Space Systems/Loral (M/S G87)  FAX:    (415) 852-6286
| 3825 Fabian Way                E-MAIL: bard@cutter.ssd.loral.com
| Palo Alto, CA  9430
|

ckp@grebyn.com (Checkpoint Technologies) (06/05/91)

In article <1991Jun4.233928.5185@athena.mit.edu> scs@adam.mit.edu writes:
>In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com (Frank P. Bresz) writes:
>>	if ( (i=1) == (i=2) )
>>
>>Is somebody wrong or is the behavior undefined?
>>Personal opinion: I think the behaviour is undefined by K&R anyway I can't
>>say for ANSI.
>
>Of course it's undefined.  (It contains two side effects not
>separated by a sequence point.)

You know, that was my first impression.  But after thinking about it,
I'm not so sure.

You see, I think the (i=1) should evaluate to the value 1, and the (i=2)
should evaluate to the value 2, regardless of the order in which they're
performed.  The order of operations will give the resulting value for i
after the if statement. The variable i is not fetched during the entire
statement, so the order in which the variable is stored should not
matter.  Unless someone thinks the compiler should evaluate (i = 1) by
storing 1 in i, then fetch that value back some time later for the
comparison, but I seem to recall some ANSI rules about how many times a
storage object may be touched between sequence points.

-- 
Richard Krehbiel, private citizen      ckp@grebyn.com
(Who needs a fancy .signature?)

grogers@convex.com (Geoffrey Rogers) (06/05/91)

In article <1991Jun5.014758.10616@wdl1.wdl.loral.com> bard@cutter.ssd.loral.com (J H Woodyatt) writes:
>In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu (Steve Summit) writes:
>|> In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com (Frank P. Bresz) writes:
>|> >	if ( (i=1) == (i=2) )
>|> >
>|> >Is somebody wrong or is the behavior undefined?

The behavior of this expression is undefined. Section 3.3 states

Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the
value to be stored.[34]

Footnote 34:

34. This paragraph renders undefined statement expressions such as

	i = ++i + 1;

    while allowing

	i = i + 1;

Also you have an evaluation order problem here. Which subexpression do
you execute first i=1 or i=2? Again this is undefined.

>My 2nd edition K&R book says in the glossary (p.208) that the result of an
>assignment expression is the value that was stored in the lvalue after the
>assignment takes place. Thus, independent of order of evaluation, the above
>expression should always evaluate FALSE. (Or at least so say I.)

Remember the operators = and == do  not have sequence points.

>The fact that *my* compiler seems to overlook this wording is somewhat alarming
>to me. I'd like to know what *else* it's willing to ignore, mangle or optimize
>into oblivion incorrectly.

Since the behavior is undefined for this code fragment, you can expect any
two different compilers to gave you different results.

>Which leads to an interesting question about portable programming. What fringy
>kinds of things in a standard can one expect compilers to sometimes overlook and
>thus be classifiable in the category of `Bad Programming Practice.

Anything behavior that is explicitly or implicitly defined as being
undefined (if the behavior is not defined, it is implicitly defined as
beening undefined, atleast this is what a compiler writer told me).

cheers

+------------------------------------+---------------------------------+
| Geoffrey C. Rogers   		     | "Whose brain did you get?"      |
| grogers@convex.com                 | "Abbie Normal!"                 |
| {sun,uunet,uiucdcs}!convex!grogers |                                 |
+------------------------------------+---------------------------------+

mcdaniel@adi.com (Tim McDaniel) (06/05/91)

About "if ( (i=1) == (i=2) )":

bard@cutter.ssd.loral.com (J H Woodyatt) writes:

   What fringy kinds of things in a standard can one expect compilers
   to sometimes overlook and thus be classifiable in the category of
   `Bad Programming Practice.'

Mr. Woodyatt should be more concerned about what HE overlooked:

   In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu
   (Steve Summit) writes: 
   |> The comp.lang.c frequently-asked questions list has a bit to say
   |> about undefined order of evaluation.  Did you check it first?

Frequently-Asked Questions section 3, "Order of Evaluation", questions
25 and 26.  E-mail me for a copy if it has expired on your system.
K&R discuss the subject in section 2.12, "Precedence and Order of
Evaluation", pp. 52-54; also A7, "Expressions", paragraph 2, p. 200.
(2nd edition, 1st printing.)  Look for "side effects" in the index.
Also see "C Traps and Pitfalls", by Andrew Koenig -- a fine book.

--
   "Of course he has a knife; he always has a knife.  We all have knives.
   It's 1183 and we're barbarians."
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

worley@compass.com (Dale Worley) (06/05/91)

In article <1991Jun5.014758.10616@wdl1.wdl.loral.com> bard@cutter.ssd.loral.com (J H Woodyatt) writes:
   |> >		if ( (i=1) == (i=2) )
   |> >Is somebody wrong or is the behavior undefined?
   |> Of course it's undefined.  (It contains two side effects not
   |> separated by a sequence point.)

   Is this really undefined by ANSI? I suppose we need someone with
   the STANDARD to resolve this.

ANSI C Standard, Dec. 88 draft, sec. 3.3, p. 39, l. 5:

    Between the previous and next sequence point an object shall have its
    stored value modified at most once by the evaluation of an expression.

Why don't people out there just go *buy* a copy of the standard?  It
would resolve a lot of these questions!

Dale Worley		Compass, Inc.			worley@compass.com
--
When asked how much money is enough, Nelson Rockefeller replied:
"A little bit more."

volpe@camelback.crd.ge.com (Christopher R Volpe) (06/05/91)

In article <1991Jun5.014758.10616@wdl1.wdl.loral.com>,
bard@cutter.ssd.loral.com (J H Woodyatt) writes:
|>In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu
(Steve Summit) writes:
|>|> In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com
(Frank P. Bresz) writes:
|>|> >	if ( (i=1) == (i=2) )
|>|> >
|>|> >Is somebody wrong or is the behavior undefined?
|>|> >Personal opinion: I think the behaviour is undefined by K&R anyway
I can't
|>|> >say for ANSI.
|>|> 
|>|> Of course it's undefined.  (It contains two side effects not
|>|> separated by a sequence point.)
|>
|>Is this really undefined by ANSI? I suppose we need someone with the
STANDARD to
|>resolve this. (I'm politely assuming that there is a good reason for
wanting to
|>though I'm unable to think of one.)
|>
|>My 2nd edition K&R book says in the glossary (p.208) that the result of an
|>assignment expression is the value that was stored in the lvalue after the
|>assignment takes place. Thus, independent of order of evaluation, the above
|>expression should always evaluate FALSE. (Or at least so say I.)

Yes, it is undefined according to ANSI. It has nothing to do with order
of evaluation, though. You are right about the value of each assignment
expression, but that's not the point. The problem, as Steve pointed out,
is that the value of "i" is modified twice between sequence points. As
a result, all bets are off, since the Standard says that this is not allowed
and that anything can happen if you do it.

-Chris

|>|
|>| James Woodyatt                 VOICE:  (415) 852-5429
|>| Space Systems/Loral (M/S G87)  FAX:    (415) 852-6286
|>| 3825 Fabian Way                E-MAIL: bard@cutter.ssd.loral.com
|>| Palo Alto, CA  9430
|>|
                                   
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

scs@adam.mit.edu (Steve Summit) (06/05/91)

In article <1991Jun5.014758.10616@wdl1.wdl.loral.com> bard@cutter.ssd.loral.com (J H Woodyatt) writes:
>In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu (Steve Summit) writes:
>|> Of course it's undefined.  (It contains two side effects not
>|> separated by a sequence point.)
>
>Is this really undefined by ANSI? I suppose we need someone with the STANDARD to
>resolve this.

I *do* have a copy of the Standard.  In a (futile) attempt to
head this discussion off early, I posted my followup from memory,
before going home so that I could quote chapter and verse out of
my copy.  (Several people have since done so.)

I did mention, and you seem to have ignored, my justification
(which paraphrases the Standard): "...It contains two side
effects not separated by a sequence point."

>Which leads to an interesting question about portable programming. What fringy
>kinds of things in a standard can one expect compilers to sometimes overlook and
>thus be classifiable in the category of `Bad Programming Practice.'

This was just mentioned, but it's worth mentioning again:
depending on any unspecified or undefined aspects of a language
is certainly in the category of "bad programming practice."
(Actually, in my own work, I also avoid everything I feel is
"fringy," but I realize that's somewhat harder to quantify
objectively.  As an example, I never depended on free() leaving
the contents of freed memory undisturbed, even though old
versions of the malloc man page asserted that it did.)

K&R is loaded with good advice, although they don't hit you over
the head with a brick by setting it off in a sidebar with a
header like "Brian & Dennis's Programming Tip #42."  Once again,
as they say, "if you don't know how [undefined things] are done
on various machines, that innocence may help to protect you."

In article <1991Jun5.123931.22105@grebyn.com> ckp@grebyn.com writes:
>You see, I think the (i=1) should evaluate to the value 1, and the (i=2)
>should evaluate to the value 2, regardless of the order in which they're
>performed...  The variable i is not fetched during the entire
>statement, so the order in which the variable is stored should not
>matter.  Unless someone thinks the compiler should evaluate (i = 1) by
>storing 1 in i, then fetch that value back some time later for the
>comparison, but I seem to recall some ANSI rules about how many times a
>storage object may be touched between sequence points.

The rules about how many times a storage object may be "touched"
between sequence points (as I recall; my copy of the Standard is
still at home) cover: how often a programmer may attempt (in
source code) to modify an object, how often a programmer may
attempt to access a volatile object, and what code the compiler
may generate for volatile objects.  They do not make

	(i = 1) == (i = 2)

any less undefined.

In fact, it's not at all unreasonable for the compiler to
"evaluate (i = 1) by storing 1 in i, then fetch that value back
some time later" (this issue was discussed a few months ago,
either here or on comp.std.c).  Remember that the result of an
assignment is the result after assignment, including the cast to
the type of the left-hand-side.  If we had the code

	char c1, c2;
	c1 = c2 = 5.;

I would certainly expect the compiler to emit code to convert the
value five into a char value, placing the result into c2, and
then fetch c2 and place it into c1, rather than doing the
conversion twice.  Let's try it:

	Script started on Wed Jun  5 12:12:26 1991
	adam> /lib/ccom
	f()
	{
	char c1, c2;
	c1 = c2 = 5.;
		cvtlb	$5,-2(fp)
		movb	-2(fp),-1(fp)
	}
		ret

This is on a VAX (which has nice readable instruction mnemonics);
I've elided the subroutine preamble from the output.  The
compiler didn't bother to emit a floating-point constant or a
run-time floating-point conversion, but rather a longword
(integral) 5 and a convert-longword-to-byte instruction.  As
expected, it then re-fetches c2 (stored at -2(fp)) before moving
the (byte) value to c1 (-1(fp)).

There's nothing magic or devious going on here.  pcc is not an
aggressively-optimizing compiler; this fetch-after-store is in
fact a very natural way for a compiler to handle the value of an
assignment statement.  (A C interpreter I once wrote did the same
thing, although there's a note in the source code indicating that
it caused me problems when I was attempting to assign to device
registers with funny read/write semantics, particularly because
the interpreter always fetched the result of an assignment
whether it was needed or not.)

Of course, we really don't need to think in detail about how
assignments are performed to answer the original question.  Since
the expression in question contains two side effects between
sequence points, its behavior is undefined [note 1], and the
compiler is free to <insert favorite ludicrous prove-a-point
weird undefined compiler behavior>, no matter how "unreasonable."

                                            Steve Summit
                                            scs@adam.mit.edu

Note 1 (again from memory): the behavior of

	(i = 1) == (i = 2)

is undefined, though it is not required to elicit a diagnostic,
because it violates a "shall" statement outside of a constraint.

Anyone who desires references for any of the assertions made in
this article may send me mail; I'll respond to them when I have a
copy of the Standard handy.

DOCTORJ@SLACVM.SLAC.STANFORD.EDU (Jon J Thaler) (06/06/91)

In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu (Steve
Summit) says:

>> [...discussion of this expression deleted...]
>>       if ( (i=1) == (i=2) )

>Of course it's undefined.  (It contains two side effects not
>separated by a sequence point.)  Given that the behavior is
>undefined, I'd say it's fairly pointless to catalog the behavior
>of available compilers.  As Kernighan and Ritchie point out, and
>I am fond of quoting, "if you don't know how they are done on
>various machines, that innocence may help to protect you."

When must a compiler issue warnings or other error messages? It seems to
me that since this expression is recognizable as an error, a compiler
'ought' to warn the user.  As far as I can tell, this does not seem to be
required by the standard.

henry@zoo.toronto.edu (Henry Spencer) (06/06/91)

In article <91156.095107DOCTORJ@SLACVM.SLAC.STANFORD.EDU> DOCTORJ@SLACVM.SLAC.STANFORD.EDU (Jon J Thaler) writes:
>>>       if ( (i=1) == (i=2) )
>
>When must a compiler issue warnings or other error messages? It seems to
>me that since this expression is recognizable as an error, a compiler
>'ought' to warn the user.  As far as I can tell, this does not seem to be
>required by the standard.

The problem is that the references to the same variable may be done via
pointers etc., and might be very difficult to recognize at compile time.
So it is not realistic to demand that a compiler diagnose all violations
of this particular rule.

Of course, it is nice if it *does* diagnose them when it notices them.
In general, most any "undefined" item in the standard is something that
a good compiler ought to *try* to notice and report.

The only requirement the standard puts on diagnostics is that a program
which violates the standard's official constraints shall draw at least
one complaint.  Implementations vary so enormously (consider compilers
vs. interpreters, for example) that it was not considered practical to set
any more specific requirements.
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

fpb@ittc.wec.com (Frank P. Bresz) (06/06/91)

In article <1991Jun5.014758.10616@wdl1.wdl.loral.com> bard@cutter.ssd.loral.com (J H Woodyatt) writes:
[ some of the thread removed ]

>Is this really undefined by ANSI? I suppose we need someone with the STANDARD to
>resolve this. (I'm politely assuming that there is a good reason for wanting to
>though I'm unable to think of one.)

	I am guessing you mean why in heaven's name do I want to do this,
when it's blatantly ridiculous.

	Well actually since the post is for a friend I don't,  and in fact
neither does he.  He is using C++ and this code is generated for him from
the C++ preprocessor. (AT&T I think).

	He is however C literate (unlike some others in his organization),
and delved into the generated C to try and decide why their code was
behaving differently on 2 different machines.  This is a small test he
created showing the problem.  

	The other C++ people in his group of course thought that clearly
one of the compiler vendors must be wrong and that they should be able to
call someone to get this fixed (yes corporate mindset).  He wanted to
isolate it to a programmer misunderstanding (which it is).  

	On the C++ side it was not as blatantly ridiculous (or so he tells
me).

	Thank you all very much.
--
| ()  ()  () | Frank P. Bresz   | Westinghouse Electric Corporation
|  \  /\  /  | fpb@ittc.wec.com | ITTC Simulators Department
|   \/  \/   | uunet!ittc!fpb   | Those who can, do. Those who can't, simulate.
| ---------- | +1 412 733 6749  | My opinions are mine, WEC doesn't want 'em.

bard@cutter.ssd.loral.com (J H Woodyatt) (06/07/91)

In article <20273@crdgw1.crd.ge.com>, volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
|> In article <1991Jun5.014758.10616@wdl1.wdl.loral.com>,
|> bard@cutter.ssd.loral.com (J H Woodyatt) writes:
|> |>In article <1991Jun4.233928.5185@athena.mit.edu>, scs@adam.mit.edu
|> (Steve Summit) writes:
|> |>|> In article <FPB.91Jun4174400@ittc.ittc.wec.com> fpb@ittc.wec.com
|> (Frank P. Bresz) writes:
|> |>|> >	if ( (i=1) == (i=2) )
|> |>|> >
|> |>|> >Is somebody wrong or is the behavior undefined?
|> |>|> >Personal opinion: I think the behaviour is undefined by K&R anyway
|> I can't
|> |>|> >say for ANSI.
|> |>My 2nd edition K&R book says in the glossary (p.208) that the result of an
|> |>assignment expression is the value that was stored in the lvalue after the
|> |>assignment takes place. Thus, independent of order of evaluation, the above
|> |>expression should always evaluate FALSE. (Or at least so say I.)
|> 
|> Yes, it is undefined according to ANSI. It has nothing to do with order
|> of evaluation, though. You are right about the value of each assignment
|> expression, but that's not the point. The problem, as Steve pointed out,
|> is that the value of "i" is modified twice between sequence points. As
|> a result, all bets are off, since the Standard says that this is not allowed
|> and that anything can happen if you do it.
|> 
|> -Chris
|> 
|> |>|
|> |>| James Woodyatt
|>
|> ==================
|> Chris Volpe
|> G.E. Corporate R&D
|> volpecr@crd.ge.com

<<This is a response to several posts. The above is a general reference.>>

I might submit to you that all bets are off concerning the value stored
in `i' after the expression is evaluated, but as for the result of the
expression, if *that* is undefined, then it isn't by any means intuitive.

And, by the way, I *have* a copy of the FAQ, and I *have* read it. I am
quite aware of the problem of side effects with order of evaluation; I
think the side effect in the above expression renders the value of `i'
undefined, *not* the result of the expression.

I also have a related question. Given the following:

extern volatile int k;
if (k = 1) /* Yes, this is an assignment, not an equivalence test */
    { .... }

I would expect that it is undefined whether the block after the `if'
expression will be executed. Am I right?
 __________________________________________________________________
|
| James Woodyatt                 VOICE:  (415) 852-5429
| Space Systems/Loral (M/S G87)  FAX:    (415) 852-6286
| 3825 Fabian Way                E-MAIL: bard@cutter.ssd.loral.com
| Palo Alto, CA  9430
|

torek@elf.ee.lbl.gov (Chris Torek) (06/07/91)

[Original code contained two stores to the variable `i' without an 
intevening sequence point.]

>>... all bets are off, since the Standard says that this is not allowed
>>and that anything can happen if you do it.

In article <1991Jun7.011938.11342@wdl1.wdl.loral.com>
bard@cutter.ssd.loral.com (J H Woodyatt) writes:
>I might submit to you that all bets are off concerning the value stored
>in `i' after the expression is evaluated, but as for the result of the
>expression, if *that* is undefined, then it isn't by any means intuitive.

Perhaps so; but when the result of an operation is undefined (as here),
the behaviour of the system may be completely arbitrary.  A compiler is
entirely free to compile

	if ((i = 1) == (i = 2))
		printf("hey\n");

as if it were

	printf("you dummy!\n");

>And, by the way, I *have* a copy of the FAQ, and I *have* read it. I am
>quite aware of the problem of side effects with order of evaluation; I
>think the side effect in the above expression renders the value of `i'
>undefined, *not* the result of the expression.

Nope.  The whole thing is undefined.  The system is allowed to turn into
a skunk, or fly to the moon.  *ANY*thing might happen (although betting
on one of the preceding possibilities is unwise :-) ).

>I also have a related question. Given the following:
>
>extern volatile int k;
>if (k = 1) /* Yes, this is an assignment, not an equivalence test */
>    { .... }
>
>I would expect that it is undefined whether the block after the `if'
>expression will be executed. Am I right?

No and yes.  The value of an assignment is the value of the right hand
side, converted to the type of the left hand side.  In particular, this
strongly suggests---it cannot `mean' as the `meaning' of volatile is up
to the implementation, but it can calmly `suggest' while swaying a ten
ton mallet over the implementation's head---this suggests that, given

	int i;
	volatile int *p;
	i = *p = 3;

`i' should have the value 3, and the generated code should store a value
at *p but not read any value from *p.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/07/91)

In article <WORLEY.91Jun5102646@sn1987a.compass.com>, worley@compass.com (Dale Worley) writes:

> Why don't people out there just go *buy* a copy of the standard?  It
> would resolve a lot of these questions!

In my case, because I feel I shouldn't have to.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

mcdaniel@adi.com (Tim McDaniel) (06/07/91)

In article <1991Jun7.011938.11342@wdl1.wdl.loral.com>
bard@cutter.ssd.loral.com (J H Woodyatt) writes:

   I might submit to you that all bets are off concerning the value stored
   in `i' after the expression is evaluated, but as for the result of the
   expression, if *that* is undefined, then it isn't by any means intuitive.

(*) Not intuitive *to Mr. Woodyatt*.  *I* find the ANSI C rule quite
    intuitive.

(*) Who says that anything in C has to be "intuitive"?  I suggest that
    one better guideline is "simple to remember", which is related to
    but not the same as "intuitive".
       Between the previous and next sequence point an object shall
       have its stored value modified at most once by the evaluation
       of an expression.  Furthermore, the prior value shall be
       accessed only to determine the value to be stored.
       [ANS C, section 3.3]
    is simple to remember.

(*) For the code in question, the code sequence (for a hypothetical
    memory-to-memory machine)
       MOV.I &i,#1
       MOV.I &i,#2
       CMP   &i,&i
    is intuitive to me, and certainly legal by the standard.  The
    intent of the standard is that compiler don't have to worry about
    multiple assignments between sequence points -- a considerable
    freedom.

    What about

       (*p = 1) == (*q = 2)
    
    ? It could take a lot of compiler work, in the general case, to
    get what Mr. Woodyatt call the "intuitive" result.  Code that uses
    pointers could be utterly crippled (rather than partially
    crippled on parallel machines, as is the case in C now).

--
   "Of course he has a knife; he always has a knife.  We all have knives.
   It's 1183 and we're barbarians."
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

bard@cutter.ssd.loral.com (J H Woodyatt) (06/08/91)

The pummeling I've been receiving in the mail concerning my confusion over
exactly what the ANSI standard says about assignment operations has led me
to gather my thoughts (somewhat) and ask the question I suppose is at the
bottom of my trouble. Here it is:

``When it says that the resulting value of an assignment expression is the
value stored in the left operand after the assignment has taken place, does
that mean the value *written* to the left operand, or the value that is read
(some time before the next sequence point) from the object described by the
left operand after the write has been performed?''

It's a subtle point, but it troubles me nonetheless.

I figure that the standard either explicitly states that it's the former,
it's the latter, it explicitly leaves it to the implementation, or it is
curiously silent on the matter. And, I would like to know which (without
having to go out and buy a bleeding copy of the bleeding standard).

The mail I've been getting implies that it is explicitly left to the imple-
mentation of the compiler. Is this the case?

-- 
 __________________________________________________________________
|
| James Woodyatt                 VOICE:  (415) 852-5429
| Space Systems/Loral (M/S G87)  FAX:    (415) 852-6286
| 3825 Fabian Way                E-MAIL: bard@cutter.ssd.loral.com
| Palo Alto, CA  9430
|

jon@maui.cs.ucla.edu (Jonathan Gingerich) (06/08/91)

Having raised exactly this subject several months ago, let me point out
that both sides are making valid points.  There are two distinct things
going on:

1. The description of the value of an assignment expression is sufficiently
   ambiguous in both K&RI and ANSI as to make the variability of
	((i=1)==(i=2))
   a reasonable question.  This is not directly answered in the FAQ.  It is
   not a `order of evaluation' question. It is not obvious.

2. There is no question that there is a rule in ANSI only, which says that
   expression which access the same location more than once are undefined.
   The above expression is undefined as is any other expression (to the
   best of my knowledge) that would illustrate a difference in the evaluation
   of an assignment expression.

Jon.

torek@elf.ee.lbl.gov (Chris Torek) (06/10/91)

In article <14011@dog.ee.lbl.gov> I wrote, in part:
>... The value of an assignment is the value of the right hand
>side, converted to the type of the left hand side.

I have since checked the wording of the standard, and it does not say
this at all.  Indeed, it almost (but does not quite) imply the opposite.
Since this really only matters with respect to `volatile', and since
volatile is implementation-defined anyway, it turns out that one can
say nothing at all about how

	a = b = c;

statements work, beyond this: if a and b are aliases for the same
object (e.g., if a and b are replaced with *p and *q respectively,
and p and q both point to the same object), all bets are off.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

pgheit01@ulkyvx.bitnet (06/14/91)

In article <1991Jun7.232119.17834@cs.ucla.edu>, jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
> Having raised exactly this subject several months ago, let me point out
> that both sides are making valid points.  There are two distinct things
> going on:
> 
> 1. The description of the value of an assignment expression is sufficiently
>    ambiguous in both K&RI and ANSI as to make the variability of
> 	((i=1)==(i=2))
>    a reasonable question.  This is not directly answered in the FAQ.  It is
>    not a `order of evaluation' question. It is not obvious.
> 
> 2. There is no question that there is a rule in ANSI only, which says that
>    expression which access the same location more than once are undefined.
>    The above expression is undefined as is any other expression (to the
>    best of my knowledge) that would illustrate a difference in the evaluation
>    of an assignment expression.
> 
> Jon.


AAAAAARRRRRGGGGHHHHH!

Here's how ANSI C works.  An expression (ANY EXPRESSION) returns a value in
much the same way as a function returns a value.  The expression (i = 2)
returns the value 2.  The expression (i = 1) returns the value 1.  No if's,
and's or entry points or any of that stuff.

The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates conditions 
from left to right. *ALWAYS* ANSI C short-circuits a conditional statement
*ALWAYS* (unless you tell it not to) That makes possible the type of statment

if ((x != 0) && (1/x < 9))
  STATMENT;
(note that the inner sets of parentheses are not needed, and "< 9" could be
changed to whatever you need to test. Also "x != 0" can just be "x".)

ANSI guarratees that the second statement will not be executed(and division by
zero will not result) because the statment is false after the first condition
if x == 0.

I did compile and run the code in question.  The assignments do take place. 
i takes on the value 1 after the first condition is "tested", and i takes on
the value 2 after the second condition is tested.  After the if-statement is
executed, i is and will irrepairably be 2.

My C teacher just loved to slip in questions like this one to see if anyone
knew the finer details of the precedence table. :-)

Paul == pgheit01@ulkyvx.bitnet 

Disclaimer: How could U of L really accept anything this well-defined as an
official policy?

volpe@camelback.crd.ge.com (Christopher R Volpe) (06/14/91)

In article <1991Jun13.184843.508@ulkyvx.bitnet>, pgheit01@ulkyvx.bitnet writes:
|>
|>Here's how ANSI C works.  An expression (ANY EXPRESSION) returns a value in
|>much the same way as a function returns a value. 

Really? Expressions "yield" values. Functions "return" them. The mechanism
is probably not all that similar, although this is an unimportant point
right now.

|> The expression (i = 2)
|>returns the value 2.  The expression (i = 1) returns the value 1.  No if's,
|>and's or entry points or any of that stuff.

Not relevant.

|>
|>The statement if ((i = 1) == (i = 2)) is valid.  

No it's not. RTFS.

|>ANSI C evaluates conditions 
|>from left to right.

No. It evaluates the left operand of a "||" or "&&" operator before
the right operand. But it's perfectly free to evaluate the right operand of
"==" before the left operand. Of course, order of evaluation is not 
even the issue here anyway. The issue is assignment semantics. An
implementation
is free to do the following operations:

Store 2 in i.
Store 1 in i.
Get value of i as first operand.
Get value of i as second operand. 
Compare fist operand to second operand.

|> *ALWAYS* ANSI C short-circuits a conditional statement

Irrelevant. There is no short circuiting in "((i=1) == (i=2))".

|>*ALWAYS* (unless you tell it not to) 

How do you tell it not to short circuit "&&" or "||"??? You can't.

|>That makes possible the type of statment
|>
|>if ((x != 0) && (1/x < 9))
|>  STATMENT;
|>(note that the inner sets of parentheses are not needed, and "< 9" could be
|>changed to whatever you need to test. Also "x != 0" can just be "x".)

What are you talking about? The above statement is correct, but has absolutely
nothing to do with this discussion.

|>
|>ANSI guarratees that the second statement will not be executed(and
division by
|>zero will not result) because the statment is false after the first condition
|>if x == 0.

Again, so what?

|>I did compile and run the code in question.  The assignments do take place. 

Oh good. "Proof by example". 

|>i takes on the value 1 after the first condition is "tested", and i takes on
|>the value 2 after the second condition is tested.  After the if-statement is
|>executed, i is and will irrepairably be 2.

Lucky you. The behavior is undefined. It can do anything, including what
you'd like it to do. Just don't rely on it.

|>My C teacher just loved to slip in questions like this one to see if anyone
|>knew the finer details of the precedence table. :-)

Good. Now that you're an expert on operator precedence you can learn the
finer details of assignment semantics.

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

fin@norge.unet.umn.edu (Craig A. Finseth) (06/14/91)

In article <1991Jun13.184843.508@ulkyvx.bitnet> pgheit01@ulkyvx.bitnet writes:
>In article <1991Jun7.232119.17834@cs.ucla.edu>, jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>> 1. The description of the value of an assignment expression is sufficiently
>>    ambiguous in both K&RI and ANSI as to make the variability of
>> 	((i=1)==(i=2))
>>    a reasonable question.  This is not directly answered in the FAQ.  It is
>>    not a `order of evaluation' question. It is not obvious.
>> 
>> 2. There is no question that there is a rule in ANSI only, which says that
>>    expression which access the same location more than once are undefined.
>>    The above expression is undefined as is any other expression (to the
>>    best of my knowledge) that would illustrate a difference in the evaluation
>>    of an assignment expression.

>AAAAAARRRRRGGGGHHHHH!

>Here's how ANSI C works.  An expression (ANY EXPRESSION) returns a value in
>much the same way as a function returns a value.  The expression (i = 2)
	...

Correct.

>The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates conditions 

Not correct.  Even though the sub-parts of the expression, taken
separately, are valid, it does not follow that the entire statement is
valid.

>from left to right. *ALWAYS* ANSI C short-circuits a conditional statement
>*ALWAYS* (unless you tell it not to) That makes possible the type of statment

[ Digression about short-circuit evaluation of && and || and
precendence omitted.  Irrelevant to this question. ]

>I did compile and run the code in question.  The assignments do take place. 
>i takes on the value 1 after the first condition is "tested", and i takes on
>the value 2 after the second condition is tested.  After the if-statement is
>executed, i is and will irrepairably be 2.

ANSI says that the expression is undefiend.  A compiler behaving as
you described does not violate the standard.  When arguing that a
particular behavior should be defined, it is *never* useful to cite
any particular implementation or collection of implementations.

>My C teacher just loved to slip in questions like this one to see if anyone
>knew the finer details of the precedence table. :-)

I'm glad that your teacher is concentrating on these pressing issues.
He or she certainly wouldn't want to get involved in such messy issues
as what it means to conform to standards, the meaning of "undefined,"
or other portability-related issues.  [Many (:-)s for those of you who
couldn't deduce them from the wording.]

Craig A. Finseth			fin@unet.umn.edu [CAF13]
Networking Services			+1 612 624 3375 desk
University of Minnesota			+1 612 625 0006 problems
130 Lind Hall, 207 Church St SE		+1 612 626 1002 FAX
Minneapolis MN 55455-0134, USA

sa1z+@andrew.cmu.edu (Sudheer Apte) (06/14/91)

pgheit01@ulkyvx.bitnet writes:
> 
> [...]    AAAAAARRRRRGGGGHHHHH!                [...]
> 
> The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates
> conditions from left to right. *ALWAYS* ANSI C short-circuits a
> conditional statement *ALWAYS* (unless you tell it not to) 

Hmm.  Since you'll probably be flamed out of existence for this, I
won't bother.  (In case you haven't yet figured it out, '==' is not
guaranteed anywhere to evaluate left-to-right.  Your second example
[deleted] doesn't use '==', and is correct.)

I just have a suggestion to make to Steve Summit:  do you think this
is a good question to put in the FAQ?  I vote to put it in.

Thanks,
	Sudheer.
----------------
...{harvard, uunet}!andrew.cmu.edu!sa1z
sa1z%andrew.cmu.edu@CARNEGIE

tim@proton.amd.com (Tim Olson) (06/14/91)

In article <1991Jun13.184843.508@ulkyvx.bitnet> pgheit01@ulkyvx.bitnet writes:
| AAAAAARRRRRGGGGHHHHH!
| 
| The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates conditions 
| from left to right. *ALWAYS* ANSI C short-circuits a conditional statement
| *ALWAYS* (unless you tell it not to) That makes possible the type of statment
| if ((x != 0) && (1/x < 9))
|   STATMENT;
| (note that the inner sets of parentheses are not needed, and "< 9" could be
| changed to whatever you need to test. Also "x != 0" can just be "x".)
| 
| ANSI guarratees that the second statement will not be executed(and division by
| zero will not result) because the statment is false after the first condition
| if x == 0.

There are a number of fallacies in the statement above.  The
expression

	((i=1) == (i=2)) is not valid, because the ANSI spec specifies
that (3.3 EXPRESSIONS):

	"Between the previous and next sequence point an object shall
	 have its stored value modified at most once by the evaluation
	 of an expression."

Furthermore, the spec states that (3.3 EXPRESSIONS):

	"Except [for operators] (), &&, ||, ?:, and "comma", the order
	 of evaluation of subexpressions and the order in which side
	 effects take place are both unspecified."

The == operator is not a short-circuit operator, and the order of
evaluation of its operands is undefined.


| I did compile and run the code in question.  The assignments do take place. 
| i takes on the value 1 after the first condition is "tested", and i takes on
| the value 2 after the second condition is tested.  After the if-statement is
| executed, i is and will irrepairably be 2.

That is not a proof, it is just an example.  Here is a counterexample:

;1   |int i;
;2   |
;3   |f()
;4   |{
;5   |    return ((i=1) == (i=2));
	const	gr97,_i
	const	gr96,2	; (0x2)
	consth	gr97,_i
	store	0,0,gr96,gr97
;6   |}
	jmpi	lr0
	const	gr96,1	; (0x1)

Yep -- the compiler generated code to store the value '2' into i, but
returned a '1' as the value of the expression.  This is valid code for
the given expression.


| My C teacher just loved to slip in questions like this one to see if anyone
| knew the finer details of the precedence table. :-)

This has nothing to do with precedence.

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

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

bhoughto@nevin.intel.com (Blair P. Houghton) (06/16/91)

In article <20575@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>In article <1991Jun13.184843.508@ulkyvx.bitnet>, pgheit01@ulkyvx.bitnet writes:
>|>*ALWAYS* (unless you tell it not to) 
>
>How do you tell it not to short circuit "&&" or "||"??? You can't.

Not as such, but,

	... ( e1 && e2 ) ...

is the same as

	v1 = e1;
	v2 = e2;
	... ( v1 && v2 ) ...

If you want the order of evaluation of expressions
to be defined, then define the order of evaluation by
evaluating them in that order.  The language defines
many ways to evaluate expressions in a defined order.

				--Blair
				  "It won't kill you, nor
				   will anyone who has anything
				   better to do laugh at you."

daniel@sdl.mdcbbs.com (06/16/91)

In article <1991Jun13.184843.508@ulkyvx.bitnet>, pgheit01@ulkyvx.bitnet writes:
> In article <1991Jun7.232119.17834@cs.ucla.edu>, jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>> Having raised exactly this subject several months ago, let me point out
>> that both sides are making valid points.  There are two distinct things
>> going on:
>> 
>> 1. The description of the value of an assignment expression is sufficiently
>>    ambiguous in both K&RI and ANSI as to make the variability of
>> 	((i=1)==(i=2))
>>    a reasonable question.  This is not directly answered in the FAQ.  It is
>>    not a `order of evaluation' question. It is not obvious.
>> 
>> 2. There is no question that there is a rule in ANSI only, which says that
>>    expression which access the same location more than once are undefined.
>>    The above expression is undefined as is any other expression (to the
>>    best of my knowledge) that would illustrate a difference in the evaluation
>>    of an assignment expression.
>> 
>> Jon.
> 
> 
> AAAAAARRRRRGGGGHHHHH!
> 
> Here's how ANSI C works.  An expression (ANY EXPRESSION) returns a value in
> much the same way as a function returns a value.  The expression (i = 2)
> returns the value 2.  The expression (i = 1) returns the value 1.  No if's,
> and's or entry points or any of that stuff.
> 
> The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates conditions 
> from left to right. *ALWAYS* ANSI C short-circuits a conditional statement
> *ALWAYS* (unless you tell it not to) That makes possible the type of statment
> 
> if ((x != 0) && (1/x < 9))
>   STATMENT;
> (note that the inner sets of parentheses are not needed, and "< 9" could be
> changed to whatever you need to test. Also "x != 0" can just be "x".)
> 
> ANSI guarratees that the second statement will not be executed(and division by
> zero will not result) because the statment is false after the first condition
> if x == 0.
> 
> I did compile and run the code in question.  The assignments do take place. 
> i takes on the value 1 after the first condition is "tested", and i takes on
> the value 2 after the second condition is tested.  After the if-statement is
> executed, i is and will irrepairably be 2.
> 
> My C teacher just loved to slip in questions like this one to see if anyone
> knew the finer details of the precedence table. :-)
> 
> Paul == pgheit01@ulkyvx.bitnet 
> 
> Disclaimer: How could U of L really accept anything this well-defined as an
> official policy?
-- 
Daniel Dignam                           Shape Data Limited (McDonnell Douglas)
 Internet: daniel@sdl.mdcbbs.com           46 Regent Street
     UUCP: ...!uunet!sdl.mdcbbs.com!daniel   Cambridge CB2 1DB
    Voice: +44 223 316673  Fax: +44 223 316931  United Kingdom

daniel@sdl.mdcbbs.com (06/16/91)

Sorry about the previous posting, got news_edit logical wrong.

In article <1991Jun13.184843.508@ulkyvx.bitnet>, pgheit01@ulkyvx.bitnet writes:

> The statement if ((i = 1) == (i = 2)) is valid.  ANSI C evaluates conditions
> from left to right. *ALWAYS* ANSI C short-circuits a conditional statement
> *ALWAYS* (unless you tell it not to) That makes possible the type of statment


A quick perusal of my ANSI C spec indicates this is not correct.
Section 3.3  reads :-

    "Except as indicated by the syntax or otherwise specified later (for the
function call (), &&, ||, ?:, and comma operators), the order of evaluation
of subexpressions and the order in which side effects take place are both 
unspecified."

So you are correct about && but not about ==.

Section 3.3 also reads

    "Between the previous and next sequence point an object shall
have its stored value modified at most once by the evaluation of an expression. 
Furthermore, the prior value shall be accessed only to determine the value
to be stored. (ftnote 25)"

"(ftnote 25)
This paragraph renders undefined statement expressions such as
    i = ++i + 1;
whilst allowing
    i = i + 1;
"                

On assigment operators the ansi standard states that 

   "An assigment expression has the value of the left operand after the 
assignment, but is not an lvalue""..."The side effect of updating the stored
 value of the left  operand shall occur between the previous and the next 
sequence point."

Now my copy of the standard is only a draft, so it may have been updated to
cover this rather nasty case. But my guess is that it hasn't. Anyway where 
does this leave us? My guess is that the value of the the expression in 
question is completely undefined (as is thevalue stored in i). A straw poll 
of the 'ANSI' C compilers in house yields the following results for the 
given code.

#include <stdio.h>

main(int argc,char **argv)
  {
    int i = 0;

    if ((i = 1) == (i = 2))
      {
        printf("Branch 1, i = %d\n",i);
      }
    else
      {
        printf("Branch 2, i = %d\n",i);
      }
  }

Sun :-
Branch 1, i = 2

Vax :-
Branch 1, i = 2  

Apollo :-
Branch 1, i = 2


However K&R variants produce different results

Sun :-
Branch 2, i = 1

Dec Risc:-
Branch 1, i = 2


Read these results as you will, to me it merely confirms that exepressions
with side effects should be avoided at all costs. Indeed we have developed 
an in House C variant which produces errors for these sorts of problems.

This case is an interesting example of hard to is to provide a 'complete' 
specification for a piece of code. After all an ANSI C compiler isn't
one of the largest pieces of software around. And, if we can't get the
specification for something as well defined (obviously not that well
defined as a compiler correct, where does that leave us with respect 
to some of the larger more complex software projects around 
(air traffic control, fly by wire ......)?

                                                              
Daniel Dignam                           Shape Data Limited (McDonnell Douglas)
 Internet: daniel@sdl.mdcbbs.com           46 Regent Street
     UUCP: ...!uunet!sdl.mdcbbs.com!daniel   Cambridge CB2 1DB
    Voice: +44 223 316673  Fax: +44 223 316931  United Kingdom

torek@elf.ee.lbl.gov (Chris Torek) (06/18/91)

Others have cleared up the rest of this already, but one point remains.
To avoid confusion, I will also restate some of the previous corrections.

In article <1991Jun13.184843.508@ulkyvx.bitnet> pgheit01@ulkyvx.bitnet writes:
>The statement if ((i = 1) == (i = 2)) is valid.

Syntactically, yes; semantically, no.

>ANSI C evaluates conditions from left to right.

False; evaluation proceeds from sequence point to sequence point in an
otherwise undefined manner (with some exceptions; see the standard for
exact details).  The short-circuit boolean-result operators && and ||
introduce sequence points, so the left hand side of any such operator
is evaluated before the right hand side, and evaluation stops as soon as
the result is known; but little else can be said.  Certainly `left to
right' is far too strong a statement.

>My C teacher just loved to slip in questions like this one to see if anyone
>knew the finer details of the precedence table. :-)

Evaluation order and precedence are orthogonal concepts.  For instance,
consider the order and precedence relations in:

	i = *p++;

Precedence affects the parsing of `*p++' so that it is interpreted as
*(p++) and not (*p)++, and (i = (*(p++))) and not (i = *p)++.  The most
likely evaluation order on many machines, however, is this:

	tmp = *p;
	i = tmp;
	p++;

rather than the `direct' but inefficient sequence:

	tmp = p;
	p++;
	tmp = *tmp;
	i = tmp;

You would do future students a great service to go to your C teacher
and tell him, her, or it% to obtain and read a copy of X3.159-1989, the
ANSI C standard.  [%Perhaps the C teacher is a CAI program.  `He' alone
may be sexist, but `s/he' and variants are animist.  Personally, I
think we should just give in and use `it' as the generic third-person
singular.$]  [$If you needed a half-smiley here, you are not reading
these footnotes with the proper dry tone.  (How do you tell a CAI
program to read the standard, anyway?)]  Teachers who concentrate on
syntax over semantics are probably missing the point.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

steve@taumet.com (Stephen Clamage) (06/18/91)

daniel@sdl.mdcbbs.com writes:

>    if ((i = 1) == (i = 2)) ...

>Read these results as you will, to me it merely confirms that exepressions
>with side effects should be avoided at all costs...

Not necessarily, but one most certainly should avoid multiple side-effects
between sequence points.

>This case is an interesting example of hard to is to provide a 'complete' 
>specification for a piece of code. After all an ANSI C compiler isn't
>one of the largest pieces of software around. And, if we can't get the
>specification for something as well defined (obviously not that well
>defined as a compiler correct, where does that leave us with respect 
>to some of the larger more complex software projects around 
>(air traffic control, fly by wire ......)?

This is not a difficulty of specification.  One could provide required
semantics for the above example, but it was a deliberate choice to
leave such things undefined.  Over-specification would force compiler
implementors to generate inefficient code in many cases in order to
satisfy the requirements of pathological programs like the above.

-- 

Steve Clamage, TauMetric Corp, steve@taumet.com