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! ]
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
bo...@telia.com
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
> 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.
It's undefined behavior. There is no guarantee that the left or the right side
of the assignment are evaluated first.
sm
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
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
> A simple question for some c++ guru:
>
> in this line of code
>
> i = 1;
> s[i] = s[--i];
The code has undefined behavior.
> 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.
> 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
>>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.
--
Ed Avis <e...@membled.com>
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.
--
Andrew Koenig, a...@acm.org
> "Bo Persson" <bo...@telia.com> writes:
>
>>>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.
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.
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;
--
Ed Avis <e...@membled.com>
> >>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.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
> 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?
Yes. The rule has several important advantages:
- It generates considerable traffic in the newsgroups. I mean, what
would we discuss here if we didn't have such issues? And of course,
the more traffic in the newsgroups, the more the language seems
important.
- It always us experts to show off, by showing that we understand such
subtlies. Also, subtle difficulties in the language, which cause
problems for the beginner, make the language seem harder than it
really is, which in turn means that consultants in the language can
ask for (and get) higher rates.
Those are about the only real reasons I can think of, but you'll have to
admit that the last one is absolutely conclusive.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée 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 ]