Topic: evaluation order of arr[i]=i=j


Author: "Alastair J. Houghton" <ajh8@doc.ic.ac.uk>
Date: 1999/10/27
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote in message
news:3811d3ee.21574984@news.csrlink.net...

[snip]

> Is that enough?  We get undefined behavior when using the old value
> of something which is modified for any purpose other than to determine
> the new value.
>
>    p = p->next;     // well defined
>
>    p->next = p = 0; // a[i] = i = j obviously undefined, it could work

Nonesense. Both statements are well-defined;

  p->next = p = 0;

will cause most machines to flag an exception, because the
evaluation order is right-to left and p has already been set
to null.

  a[i] = i = j;

amounts to

  i = j; a[j] = j;

which is fine as far as I can see.

>    p = p->next = 0; // i = a[i] = j still undefined

Similarly,

  p = p->next = 0;

is the same as

  p->next = 0; p = p->next;

which is also fine, as does

  i = a[i] = j;

which just does

  a[i] = j; i = j;

Evaluation order of the "=" operator *is* defined as right-to-left.

> In the last case, there seems to be no way to produce undefined
> behavior since the parameter p->next (a[i]) must be evaluated prior
> to making the assignment to p (i).  The associativity is right to left
> and common sense says this is well defined.  The standard says
> otherwise.  The value to be stored in p (i) does not depend upon
> evaluation of p->next (a[i]).

All the values are well-defined except for the first pointer case,
which will cause a crash on most systems (but that's because of
the system architecture and not the really anything to do with
the language).

I'm virtually certain that this is what the standard says - it's
certainly been my understanding of the situation for several
years.

Alastair Houghton
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Alastair J. Houghton" <ajh8@doc.ic.ac.uk>
Date: 1999/10/27
Raw View
Alastair J. Houghton <ajh8@doc.ic.ac.uk> wrote in message
news:7v4tua$a1h$1@supernews.com...
> John Potter <jpotter@falcon.lhup.edu> wrote in message
> news:3811d3ee.21574984@news.csrlink.net...

[snip]

I'm sorry. It seems I jumped in to this both feet first.
John is of course correct. I still maintain that my
previous post is the way it *should* be (but it *ISN'T*
what the standard says - the standard DOESN'T define
the evaluation order of '=', it defines the associativity
and operator precedence; I should have checked my facts
before posting ;-]).

Thanks Valentin for pointing this out, and my apologies
again.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: comeau@panix.com (Greg Comeau)
Date: 1999/10/27
Raw View
In article <7v4tua$a1h$1@supernews.com> "Alastair J. Houghton" <ajh8@doc.ic.ac.uk> writes:
>  a[i] = i = j;
>
>amounts to
>
>  i = j; a[j] = j;
>
>which is fine as far as I can see.
....
> <snipped various other similar cases>
>....
>I'm virtually certain that this is what the standard says - it's
>certainly been my understanding of the situation for several
>years.

It's easy to think the above because some of the terms
are intertwined, but it's not what the standard says.
If you disagree, you can be certain by checking out the Standard.

- Greg
--
       Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
     Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
    Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
                *** WEB: http://www.comeaucomputing.com ***
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/10/28
Raw View
"Alastair J. Houghton" <ajh8@doc.ic.ac.uk> writes:

>John Potter <jpotter@falcon.lhup.edu> wrote in message
>news:3811d3ee.21574984@news.csrlink.net...

>> Is that enough?  We get undefined behavior when using the old value
>> of something which is modified for any purpose other than to determine
>> the new value.
>>
>>    p = p->next;     // well defined
>>
>>    p->next = p = 0; // a[i] = i = j obviously undefined, it could work

>Nonesense. Both statements are well-defined;

>  p->next = p = 0;

>will cause most machines to flag an exception, because the
>evaluation order is right-to left and p has already been set
>to null.

Not so, because there is no sequence point in the statement.
The VALUE of (p=0) is assigned to p->next, but the side effect
of modifying variable p can occur at any time up to the end
of the entire statement. Variable p is both read and modified
with no intervening sequence point, so the results are undefined.


>  a[i] = i = j;

>amounts to

>  i = j; a[j] = j;

No, it doesn't.

There is no sequence point in the original statement, but the
rewritten version inserts one (the semicolon).

In the original version, variable i is both read and modified
without an intervening sequence point, so the results are undefined.


>Evaluation order of the "=" operator *is* defined as right-to-left.

Not so. The assignment operator *associates* right to left.
That establishes a partial ordering, not a total ordering.
The completion of side effects is determined by the location
of sequence points, and there is no sequence point associated
with an assignment operator.

>I'm virtually certain that this is what the standard says - it's
>certainly been my understanding of the situation for several
>years.

Your understanding is not correct. Read in particular section
1.9 "Program execution" in the standard. These semantics are
unchanged from C.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1999/10/24
Raw View
On 22 Oct 99 05:08:04 GMT, James.Kanze@dresdner-bank.com wrote:

: In article <380CBE26.62F5@wanadoo.fr>,
:   Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
: > James.Kanze@dresdner-bank.com wrote:
:
: > > In article <380773AD.749B@wanadoo.fr>,
: > >   Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
: > > > In general (that is, except for lazy operators), the order of
: > > > evaluation is unspecified in every good programming
: > > > language.</TROLL>
: > Code which depends on the left-hand side of an eager operator
: > being evaluated before the right-hand side has nothing to do in
: > serious programs.</serious>
:
: I agree totally.  However, code is written by humans, and sometimes we
: make mistakes.  One of the advantages of a fixed evaluation order is
: that it either works, or it doesn't, and a test will reveal it.
:
: At any rate, you made a definite statement, independant of context, that
: the order of evaluation is unspecified in every good programming
: language.  I think that the example in question is a very good argument
: for at least partially specifying it.  I think that reproducibility in
: general is a very good argument for fully specifying it.

Is that enough?  We get undefined behavior when using the old value
of something which is modified for any purpose other than to determine
the new value.

   p = p->next;     // well defined

   p->next = p = 0; // a[i] = i = j obviously undefined, it could work

   p = p->next = 0; // i = a[i] = j still undefined

In the last case, there seems to be no way to produce undefined
behavior since the parameter p->next (a[i]) must be evaluated prior
to making the assignment to p (i).  The associativity is right to left
and common sense says this is well defined.  The standard says
otherwise.  The value to be stored in p (i) does not depend upon
evaluation of p->next (a[i]).

John
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/10/22
Raw View
In article <380BB5D8.D95DE99A@synopsys.com>,
  Gene Bushuyev <gbush@synopsys.com> wrote:
> James.Kanze@dresdner-bank.com wrote:
> [snip]

> > The above code was posted by Dave Abrahams.  One of the best experts
> > in exception safety around.  If even he has problems getting it
> > right, then I take that as a sign that there is a problem with the
> > language. The undefined behavior, in this case, is a historical
> > artifact, perfectly justified in the context in which C was
> > developped.  But it has no place in a modern language, compiled with
> > modern compilers.

> I certainly agree that it would be a boon for programmers to have the
> order of evaluation defined. But at the same time, if we fix the order
> of evaluation, we prevent compilers from generating code that would
> evaluate parameters concurrently.

Not really.  If no function calls are involved, the compiler will
generally be able to determine that there are no side effects, or that
the order of the side effects has no effect on the observable behavior
of the program, and optimize under the as if rule anyway.  And if
function calls are involved, the current rules already forbid concurrent
evaluation of functions.

Note that the rules forbidding concurrent execution of functions also
apply to inlined functions.  Never the less, the peephole optimizers on
most risc machines will move code across inlined function boundaries.

--
James Kanze                    mailto:James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/10/22
Raw View
In article <380CBE26.62F5@wanadoo.fr>,
  Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
> James.Kanze@dresdner-bank.com wrote:

> > In article <380773AD.749B@wanadoo.fr>,
> >   Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:

> > > genshirt@modicon.de wrote:

> > > > Is there any standard concerning the evalution order of an
> > > > assignment statement? Will the expression evaluated first or the
> > > > term of the left side?

> > > In general (that is, except for lazy operators), the order of
> > > evaluation is unspecified in every good programming
> > > language.</TROLL>

> > I totally agree.  Such a rule is wonderful job security for us
> > contractors.  I mean, isn't it wonderful that even something like

> >     f( auto_ptr< T >( new T ) , auto_ptr< T >( new T ) ) ;

> > isn't exception safe.

> > </satire>

> Code which depends on the left-hand side of an eager operator
> being evaluated before the right-hand side has nothing to do in
> serious programs.</serious>

I agree totally.  However, code is written by humans, and sometimes we
make mistakes.  One of the advantages of a fixed evaluation order is
that it either works, or it doesn't, and a test will reveal it.

At any rate, you made a definite statement, independant of context, that
the order of evaluation is unspecified in every good programming
language.  I think that the example in question is a very good argument
for at least partially specifying it.  I think that reproducibility in
general is a very good argument for fully specifying it.

And I've yet to hear any real convincing argument against specifying it.

> I said nothing about interlaced evaluation, which is the problem
> in Dave's code.

The problem in this code is nevertheless due to the same rule, at least
in C++.  Would you agree then that the rule needs some tightening up?
If so, what should it be?  Defining a fixed order is simple to specify
and to understand, but I'm open to other suggestions.

--
James Kanze                    mailto:James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Gene Bushuyev <gbush@synopsys.com>
Date: 1999/10/21
Raw View
James.Kanze@dresdner-bank.com wrote:
[snip]
> The above code was posted by Dave Abrahams.  One of the best experts in
> exception safety around.  If even he has problems getting it right, then
> I take that as a sign that there is a problem with the language.  The
> undefined behavior, in this case, is a historical artifact, perfectly
> justified in the context in which C was developped.  But it has no place
> in a modern language, compiled with modern compilers.

I certainly agree that it would be a boon for programmers to have the
order of evaluation defined. But at the same time, if we fix the order
of evaluation, we prevent compilers from generating code that would
evaluate parameters concurrently.
So, do we need one more reserved word in function declaration say
"ordered"?
void f(ClassA, ClassB) ordered;
is a different function than
void f(ClassA, ClassB);
that is not ordered.
Just thinking out loud.

--
Gene Bushuyev
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/21
Raw View
James.Kanze@dresdner-bank.com wrote:

> In article <380773AD.749B@wanadoo.fr>,
>   Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
>
> > genshirt@modicon.de wrote:
>
> > > Is there any standard concerning the evalution order of an
> > > assignment statement? Will the expression evaluated first or the
> > > term of the left side?
>
> > In general (that is, except for lazy operators), the order of
> > evaluation is unspecified in every good programming language.</TROLL>
>
> I totally agree.  Such a rule is wonderful job security for us
> contractors.  I mean, isn't it wonderful that even something like
>
>     f( auto_ptr< T >( new T ) , auto_ptr< T >( new T ) ) ;
>
> isn't exception safe.
>
> </satire>

Code which depends on the left-hand side of an eager operator
being evaluated before the right-hand side has nothing to do in
serious programs.</serious>

I said nothing about interlaced evaluation, which is the problem
in Dave's code.

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: genshirt@modicon.de
Date: 1999/10/15
Raw View
Is there any standard concerning the evalution order of an assignment
statement? Will the expression evaluated first or the term of the left
side? Example:

   i=1;j=2; arr[1] = 10; arr[2] = 20;  // initializations

  arr[i] = i = j;

Now what is in arr[1] and arr[2]?

   Borland 3.1:  2, 20
   VC++,5.0:     1, 2

Waiting for your answers,
Thomas






Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Ron" <nospam@this-address.org>
Date: 1999/10/15
Raw View
<genshirt@modicon.de> wrote in message news:7u7hve$mvi$1@nnrp1.deja.com...
> Is there any standard concerning the evalution order of an assignment
> statement? Will the expression evaluated first or the term of the left
> side? Example:
>
>    i=1;j=2; arr[1] = 10; arr[2] = 20;  // initializations
>
>   arr[i] = i = j;
>
> Now what is in arr[1] and arr[2]?
>
>    Borland 3.1:  2, 20
>    VC++,5.0:     1, 2

It seems that this ought to be covered by section 5.17(1), which reads:

    There are several assignment operators, all of which group
right-   to-   left. All require a modifiable lvalue
    as their left operand, and the type of an assignment expression is that
of its left operand. The result of
    the assignment operation is the value stored in the left operand after
the assignment has taken place;
    the result is an lvalue.

Grouping the expression in question right-to-left, we have

    arr[i] = (i = j)

Since j == 2, the result of (i = j) is 2. At this point, we have,
effectively, the expression

    arr [i] = 2;

which should, since i == 2, evaluate to

    arr [2] = 2;

So, the appropriate result should be arr [1] == 10 and arr [2] == 2.

Borland C++ Builder 4.0 patch 1 yields this result, both with and without
various optimizations enabled.

-- Ron




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/15
Raw View
genshirt@modicon.de wrote:

> Is there any standard concerning the evalution order of an assignment
> statement? Will the expression evaluated first or the term of the left
> side?

In general (that is, except for lazy operators), the order of evaluation
is unspecified in every good programming language.</TROLL>

> Example:
>
>    i=1;j=2; arr[1] = 10; arr[2] = 20;  // initializations
>
>   arr[i] = i = j;
>
> Now what is in arr[1] and arr[2]?

The behaviour is undefined, so arr[1] and arr[2] may have
any values, and the program can also crash your computer.

--

Valentin Bonnard


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/10/15
Raw View
"Ron" <nospam@this-address.org> writes:
> It seems that this ought to be covered by section 5.17(1)

No. Before we start the whole sequence point thread all over again,
how about just reading about it on Deja?


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: daniel@reichardt.ch (Daniel Hartmeier)
Date: 1999/10/15
Raw View
On 15 Oct 99 16:35:06 GMT, genshirt@modicon.de wrote:

> Is there any standard concerning the evalution order of an assignment
> statement? Will the expression evaluated first or the term of the left
> side? Example:
>
>    i=1;j=2; arr[1] = 10; arr[2] = 20;  // initializations
>
>   arr[i] = i = j;

5 Expressions [expr]

 4 Except where noted, the order of evaluation of operands of individual
   operators and subexpressions of individual expressions, and the order
   in which side effects take place, is unspecified. Between the
   previous an next sequence point a scalar 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. The requirements of this paragraph shall be met
   for each allowable ordering of the subexpressions of a full
   expression; otherwise the behavior is undefined.

> Now what is in arr[1] and arr[2]?

Not only is the order of evaluation unspecified (which would mean that
either (a[1]==10, a[2]==2) or (a[1]==2, a[2]==20) are possible results),
the whole behavior is undefined, because the old value of i is not only
accessed to determine the value to be stored in arr[i], but also to
determine which array element is changed.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/10/18
Raw View
In article <380773AD.749B@wanadoo.fr>,
  Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:

> genshirt@modicon.de wrote:

> > Is there any standard concerning the evalution order of an
> > assignment statement? Will the expression evaluated first or the
> > term of the left side?

> In general (that is, except for lazy operators), the order of
> evaluation is unspecified in every good programming language.</TROLL>

I totally agree.  Such a rule is wonderful job security for us
contractors.  I mean, isn't it wonderful that even something like

    f( auto_ptr< T >( new T ) , auto_ptr< T >( new T ) ) ;

isn't exception safe.

</satire>

The above code was posted by Dave Abrahams.  One of the best experts in
exception safety around.  If even he has problems getting it right, then
I take that as a sign that there is a problem with the language.  The
undefined behavior, in this case, is a historical artifact, perfectly
justified in the context in which C was developped.  But it has no place
in a modern language, compiled with modern compilers.

With regards to the optimizing potentials lost:

  - the complaining I've heard in this regard has never been from the
    people who are actually writing compilers, and know what is and
    isn't possible, and

  - if the compiler can determine that there are no side effects (and if
    there are no non-inline functions involved, it can), it is free to
    rearrange as before, under the as if rule.

--
James Kanze                    mailto:James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Before you buy.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]