order of evaluation

order of evaluation

Post by Andrea Mur » Sun, 27 Jul 2003 20:08:17



A simple question for some c++ guru:

in this line of code

i = 1;
s[i] = s[--i];

what can I tell about order of evaluation?

C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc 3.2
and assigns s[1] to s[0].

How is wrong?

Thanks in advance.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Bo Persso » Mon, 28 Jul 2003 19:33:26




 > A simple question for some c++ guru:
 >
 > in this line of code
 >
 > i = 1;
 > s[i] = s[--i];
 >
 > what can I tell about order of evaluation?

Nothing much. The assignment ought to be last (if it had been a proper
expression).

 >
 > C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc
3.2
 > and assigns s[1] to s[0].
 >
 > How is wrong?

You are wrong!  :-)

If you update an object in an expression, you cannot also use that
object for something else (except for reading its initial value,
obviously).

As you both use and update "i" in your expression, you have broken the
contract with the compiler and it is free to do anything. Not limited
to the two behaviours you have seen.

Bo Persson

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Thomas Man » Mon, 28 Jul 2003 19:45:15


Andrea Murru schrieb:

 > A simple question for some c++ guru:
 >
 > in this line of code
 >
 > i = 1;
 > s[i] = s[--i];
 >
 > what can I tell about order of evaluation?
 >
 > C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc 3.2
 > and assigns s[1] to s[0].
 >
 > How is wrong?

All three are correct.

It's undefined behavior, so simply avoid such expressions.

regards,

Thomas

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Dhru » Mon, 28 Jul 2003 19:48:08


 > A simple question for some c++ guru:
 >
 > in this line of code
 >
 > i = 1;
 > s[i] = s[--i];
 >
 > what can I tell about order of evaluation?
 >
 > C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc 3.2
 > and assigns s[1] to s[0].
 >

Both are correct (or wrong)!!!

Even I found this out a few days ago (Thanks to all who helped me
there!!!!!!).

Chp. 5:
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  previ-
   ous  and  next  sequence  point  a scalar object shall have its stored
   value modified at most once by the evaluation of an expression.   Fur-
   thermore,  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 expres-
   sion; otherwise the behavior is undefined.

 > i = 1;
 > s[i] = s[--i];

So, in this case, the behaviour is undefined, because the value i is being
read once to increment it, and then again on the lhas of the = sign, so
this double read is the one that's causing the problem.

The second part menas that even this is invalid:

int b = (s[i] = s[--i]);

Assuming that s is an array of ints.

Or, to be more general,

typeof(s[0]) b = (s[i] = s[--i]);

Regards,
-Dhruv.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Sebastian Molesk » Mon, 28 Jul 2003 19:54:22



 > A simple question for some c++ guru:
 >
 > in this line of code
 >
 > i = 1;
 > s[i] = s[--i];
 >
 > what can I tell about order of evaluation?

It's undefined behavior. There is no guarantee that the left or the right side
of the assignment are evaluated first.

sm

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Francis Glassboro » Tue, 29 Jul 2003 01:01:33




Quote:>A simple question for some c++ guru:

>in this line of code

>i = 1;
>s[i] = s[--i];

>what can I tell about order of evaluation?

--i must be evaluated before the right hand call of subscript on s the
operands of operator = must both be evaluated before it is
evaluated.

Your code has undefined behaviour because it breaches an explicit
requirement of the Standard.

i is used twice in your assignment expression statement without an
intervening sequence point. One of those uses modifies i. That is always

undefined behaviour and the resulting code can do anything it likes.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow      ACCU

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Heinz Ozwir » Tue, 29 Jul 2003 02:00:51




: A simple question for some c++ guru:
:
: in this line of code
:
: i = 1;
: s[i] = s[--i];
:
: what can I tell about order of evaluation?

a) 1 is assigned to i first.
b) i is decremented before the right side of the second statement is
evaluated.

: C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc 3.2
: and assigns s[1] to s[0].
:
: How is wrong?

None of those above. The standard does not define an order of valuation.

    Heinz

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Jack Klei » Tue, 29 Jul 2003 02:01:27



Murru) wrote in comp.lang.c++.moderated:

Quote:> A simple question for some c++ guru:

> in this line of code

> i = 1;
> s[i] = s[--i];

The code has undefined behavior.

Quote:> what can I tell about order of evaluation?

> C++ Builder 6.0 and Visual C++ 7.1 assign s[0] to s[0], while gcc 3.2
> and assigns s[1] to s[0].

> How is wrong?

The code is wrong.  Each compiler is just as correct or incorrect as any
of the others.  The code produces undefined behavior and therefore the
C++ standard literally places no requirements at all on what happens.

Quote:> Thanks in advance.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Ed Avi » Tue, 29 Jul 2003 08:50:18



>>s[i] = s[--i];
>As you both use and update "i" in your expression, you have broken
>the contract with the compiler and it is free to do anything. Not
>limited to the two behaviours you have seen.

Are you sure about this?  Another poster quoted:

Quote:>Chp. 5:

>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 and 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.

This seems to imply that the compiler can choose any ordering it likes
among the subexpressions, but it can't do the Towers of Hanoi.

--

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Andrew Koeni » Tue, 29 Jul 2003 18:50:00


 >> 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 and 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.

Ed> This seems to imply that the compiler can choose any ordering it likes
Ed> among the subexpressions, but it can't do the Towers of Hanoi.

This paragraph says (among other things) that if a scalar object is
fectched and stored between two consecutive sequence points, and the
fetch is for a purpose other than determining the value to store,
then the behavior is undefined.

In

         s[i] = s[--i];

the value of i is fetched as part of the left-hand side stored as part
of the right-hand side.  The fetch is as part of evaluating s[i], rather
than as part of determining a value to store in i.  There are no sequence
points embedded in this expression.

Therefore, the behavior is undefined.

--

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by llewell » Tue, 29 Jul 2003 18:54:16



 >
 >>>s[i] = s[--i];
 >
 >>As you both use and update "i" in your expression, you have broken
 >>the contract with the compiler and it is free to do anything. Not
 >>limited to the two behaviours you have seen.
 >
 > Are you sure about this?  Another poster quoted:
 >
 >>Chp. 5:
 >>
 >>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 and 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.
 >
 > This seems to imply that the compiler can choose any ordering it likes
 > among the subexpressions, but it can't do the Towers of Hanoi.

Reading the part I underlined, I came to the following line of
     thought:

     in '--i', i is a scalar object having its stored value modified at
         most once.

     in 's[i]' i is being accessed, but *not* to determine the value
         stored.

     Since the order of evaluation of operators is unspecified, the 'i'
         in 's[i]' may be evaluated before the '--i' in 's[--i]'. This
         would result in an access of the prior value of i.

     Since at least one ordering of the subexpressions of the full
         expression fails to meet the requirements, we have undefined
         behavior.

I'm not certain the above line of reasoning is correct, but I think
     I'll count on it until I see a sound objection.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by James Dennet » Tue, 29 Jul 2003 18:57:14



 >
 >
 >>>s[i] = s[--i];
 >
 >
 >>As you both use and update "i" in your expression, you have broken
 >>the contract with the compiler and it is free to do anything. Not
 >>limited to the two behaviours you have seen.
 >
 >
 > Are you sure about this?  Another poster quoted:
 >
 >
 >>Chp. 5:
 >>
 >>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 and 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.
 >
 >
 > This seems to imply that the compiler can choose any ordering it likes
 > among the subexpressions, but it can't do the Towers of Hanoi.
 >

Actually, the paragraph you quote gives the implementation
the freedom to do the Towers of Hanoi.  That's what the
"the requirements of this paragraph shell be met... ; otherwise
the behavior is undefined" says, speaking of requirements placed
on user code.  If you write code such that reads and writes
between sequence points break the rules, all bets are off.

This has been covered many times in the past; the archives of
comp.std.c++ will provide many repetitions, as will those of
any other major C++ newsgroup I know of.

-- James.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Hyman Rose » Wed, 30 Jul 2003 06:44:18



> I'm not certain the above line of reasoning is correct, but I think
>      I'll count on it until I see a sound objection.

How many more millions of times are we going to have to have
this same stupid thread? Why don't we just define the evaluation
order (just like Java) so that we can finally tell people that
their code is legal and exactly what it does? Does C++ really
need the grief, aggravation, and bugs that undefined order
causes?

The Java rules are exquisitely simple -
     function arguments are evaluated left to right
     operands of an operator are evaluated left to right
     lvalue "addresses" are evaluated just like rvalues

For the case in question, 's[i] = s[--i];' this would be
     1) evaluate s[i], and capture its "address" since
        it's an lvalue
     2) decrement i
     3) evaluate s[decremented-i] as an rvalue
     4) assign this rvalue to the saved lvalue

In other words, the same as writing
     s[i] = s[i - 1];
     --i;

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by Ed Avi » Wed, 30 Jul 2003 06:44:59


Thanks for the explanation, I misinterpreted 'The requirements of this
paragraph shall be met for each allowable ordering...'.  I thought it
was some kind of restriction on the compiler, but in fact it is a
restriction on user code.  If you write code where any one allowable
ordering doesn't meet the paragraph's requirements, then the behaviour
is undefined.

--

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

order of evaluation

Post by ka.. » Wed, 30 Jul 2003 06:51:28




> >>s[i] = s[--i];
> >As you both use and update "i" in your expression, you have broken
> >the contract with the compiler and it is free to do anything. Not
> >limited to the two behaviours you have seen.
> Are you sure about this?  Another poster quoted:
> >Chp. 5:
> >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 and 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.
> This seems to imply that the compiler can choose any ordering it likes
> among the subexpressions, but it can't do the Towers of Hanoi.

There are two separate issues.  A compiler is free to evaluate the
expressions in any order it pleases (modulo a few special cases not
relevant here).  If, however, in any legal ordering, you modify an
object, and access it elsewhere other than for the purpose of
determining the new value, you code has undefined behavior.  This code
comes under the second case; it is undefined behavior.

--

Conseils en informatique oriente objet/     http://www.gabi-soft.fr
                    Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

1. Order of Evaluation in Control Statements

Hello, I just got burned on this statement:

if((i = erase(i)) == end())    break;

from a member function that inherits from std::deque.

What happened to me was that the end() got evaluated before the (i = erase())
did and the latter statement caused the side-effect I wanted to test for in
the first statement.

So, my question is this:

Parameters for function calls are evaluated from right to left [at least
that's what I read somewhere].

Does the same principle hold true for control statements or is it compiler
dependent?

--
Vincent

2. Karsten's Home Page

3. Preproc: order of evaluation

4. ISDN Monitor?

5. Newbie. Order of evaluation of expressions

6. Houseview??

7. order of evaluation in aggregate initializers

8. Create GPO for Active Directory in VB

9. Order of evaluation for member function calls

10. Order of evaluation for operator parameters

11. i=i++ ? order of evaluation

12. i=i++ : order of evaluation

13. Repost: Order of evaluation of implicit parameter?