Evalution of unary subexpressions.

57 views
Skip to first unread message

Vlad from Moscow

unread,
Aug 5, 2013, 1:50:44 PM8/5/13
to std-dis...@isocpp.org
As far as I know now according to the C++ 2011 Standard the following code is well formed
 
int i = 1;
i = 1 + ++i;
 
It is interesting does the code
 
int i = 1;
int a = ++i + ++i;
 
have undefined behaviour?
 
 
 

Nathan Ernst

unread,
Aug 5, 2013, 1:52:13 PM8/5/13
to std-dis...@isocpp.org

Yes, it is undefined. You're modifying the same variable twice between sequence points.

--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
 
 

Richard Smith

unread,
Aug 5, 2013, 2:06:31 PM8/5/13
to std-dis...@isocpp.org
C++11 doesn't have sequence points. It has undefined behavior because the two side-effects on i are unsequenced.

Vlad from Moscow

unread,
Aug 5, 2013, 2:22:30 PM8/5/13
to std-dis...@isocpp.org
 
Now there is such a notion as indeterminately sequenced evaluations in the C++ Standard.
Are not the two increments indeterminately sequenced and the full expression well formed?
  
понедельник, 5 августа 2013 г., 22:06:31 UTC+4 пользователь Richard Smith написал:

Richard Smith

unread,
Aug 5, 2013, 3:01:28 PM8/5/13
to std-dis...@isocpp.org
On Mon, Aug 5, 2013 at 11:22 AM, Vlad from Moscow <vlad....@mail.ru> wrote:
 
Now there is such a notion as indeterminately sequenced evaluations in the C++ Standard.
Are not the two increments indeterminately sequenced and the full expression well formed?

No. There are only two cases where evaluations are indeterminately-sequenced:

 1) The evaluation of a function's body is indeterminately sequenced with other subexpressions in the expression containing the invocation of the function (that is, the evaluation of a function body is not interleaved with other evaluations).
 2) For a program that does not start any threads, initializations of global variables are indeterminately sequenced if they are not otherwise sequenced.
Message has been deleted

Nathan Ernst

unread,
Aug 5, 2013, 3:40:41 PM8/5/13
to std-dis...@isocpp.org

From §1.9 P15, it would appear neither example is well defined.
 

Vlad from Moscow

unread,
Aug 5, 2013, 3:47:08 PM8/5/13
to std-dis...@isocpp.org
As far as I know there was a defect report that pointed out that at least the first example is a valid code.

понедельник, 5 августа 2013 г., 23:40:41 UTC+4 пользователь Nathan Ernst написал:

Richard Smith

unread,
Aug 5, 2013, 4:35:05 PM8/5/13
to std-dis...@isocpp.org
The first example is valid.

5.3.2/1 says that `++i` is equivalent to `i+=1`.
5.17/1 says that the assignment in `i+=1` is sequenced before the value computation of the result.
1.9/15 says that the value computation of `++i` is sequenced before the value computation of the result of the expression `1 + ++i`.
5.17/1 says that the value computation of `1 + ++i` is sequenced before the assignment in `i = 1 + ++i`.

Therefore the two modifications to `i` are sequenced.

Anass Lasram

unread,
Aug 5, 2013, 5:24:33 PM8/5/13
to std-dis...@isocpp.org
One tip to avoid confusion is to replace the operator by a function call:

operator+(1, ++i); // clearly nothing wrong

operator+(++i, ++i); // no defined order therefore the behavior is undefined

Vlad from Moscow

unread,
Aug 5, 2013, 6:00:44 PM8/5/13
to std-dis...@isocpp.org
 
In this case the order is unimportant. At least MS VC++ 2010  follows the same logic as me.
 

вторник, 6 августа 2013 г., 1:24:33 UTC+4 пользователь Anass Lasram написал:

Christof Meerwald

unread,
Aug 5, 2013, 4:10:04 PM8/5/13
to std-dis...@isocpp.org
On Mon, Aug 05, 2013 at 12:47:08PM -0700, Vlad from Moscow wrote:
> As far as I know there was a defect report that pointed out that at least
> the first example is a valid code.

CWG 637:
http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#637

> >>>>> On Aug 5, 2013 12:50 PM, "Vlad from Moscow" <vlad....@mail.ru> wrote:
> >>>>>> As far as I know now according to the C++ 2011 Standard the
> >>>>>> following code is well formed
> >>>>>>
> >>>>>> int i = 1;
> >>>>>> i = 1 + ++i;


Christof

--

http://cmeerw.org sip:cmeerw at cmeerw.org
mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org

Vlad from Moscow

unread,
Aug 6, 2013, 1:19:47 PM8/6/13
to std-dis...@isocpp.org
This operator
 
operator+(++i, ++i); // no defined order therefore the behavior is undefined
 
has defined behaviour because the both side effects shall be applied before calling the operator.
 

вторник, 6 августа 2013 г., 1:24:33 UTC+4 пользователь Anass Lasram написал:
One tip to avoid confusion is to replace the operator by a function call:

Nevin Liber

unread,
Aug 6, 2013, 1:22:51 PM8/6/13
to std-dis...@isocpp.org

David Rodríguez Ibeas

unread,
Aug 6, 2013, 1:58:36 PM8/6/13
to std-dis...@isocpp.org
On Tue, Aug 6, 2013 at 1:19 PM, Vlad from Moscow <vlad....@mail.ru> wrote:
This operator
 
operator+(++i, ++i); // no defined order therefore the behavior is undefined
 
has defined behaviour because the both side effects shall be applied before calling the operator.

No, given an initial value of X for i, it is undefined whether that calls `operator+(X+1,X+2)` or `operator+(X+2,X+1)` 

Nevin Liber

unread,
Aug 6, 2013, 2:03:47 PM8/6/13
to std-dis...@isocpp.org
On 6 August 2013 12:58, David Rodríguez Ibeas <dib...@ieee.org> wrote:
On Tue, Aug 6, 2013 at 1:19 PM, Vlad from Moscow <vlad....@mail.ru> wrote:
This operator
 
operator+(++i, ++i); // no defined order therefore the behavior is undefined
 r
has defined behaviour because the both side effects shall be applied before calling the operator.

No, given an initial value of X for i, it is undefined whether that calls `operator+(X+1,X+2)` or `operator+(X+2,X+1)` 

For ints (the original example), that won't matter, since addition is commutative.

However, pick a non-commutative operation, such as subtraction:

int i = 1;
int s = --i - --i;

and you cannot predict the value of s.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Vlad from Moscow

unread,
Aug 6, 2013, 2:04:47 PM8/6/13
to std-dis...@isocpp.org, dib...@ieee.org
Given an initial value of X the compiler shall apply side effect to lvalue X after the first ++X and after the second ++X and then use this updated value of the lvalue to pass arguments to function. So the function call  does not depenf on the order in which subexpressions will be calculated. The call will be correspond to operator +( last value of the lvalue, last value of the lvalue );

вторник, 6 августа 2013 г., 21:58:36 UTC+4 пользователь David Rodríguez Ibeas написал:

Nevin Liber

unread,
Aug 6, 2013, 2:10:40 PM8/6/13
to std-dis...@isocpp.org
On 6 August 2013 13:04, Vlad from Moscow <vlad....@mail.ru> wrote:
Given an initial value of X the compiler shall apply side effect to lvalue X after the first ++X and after the second ++X and then use this updated value of the lvalue to pass arguments to function.

What section of the standard can we find that in?

I'm looking at n3290 1.9p15, but not seeing anything like that.

Vlad from Moscow

unread,
Aug 6, 2013, 2:12:42 PM8/6/13
to std-dis...@isocpp.org
This is totally the same as
 
int s = ++i + ++i;
 
and does not depend on the order of calculating subexpression.
 
After the first decrement the side effect has to be applied. As lvalue was changed the new value of the lvalue has to be reread (or read) in the second expression. It is the meaning of applying of side effects. Then again the second expression is decremented and its side effect shall be applied before operator -. The operator shall use the last value of the lvaule.
 

вторник, 6 августа 2013 г., 22:03:47 UTC+4 пользователь Nevin ":-)" Liber написал:

Nevin Liber

unread,
Aug 6, 2013, 3:04:17 PM8/6/13
to std-dis...@isocpp.org
On 6 August 2013 13:12, Vlad from Moscow <vlad....@mail.ru> wrote:
This is totally the same as
 
int s = ++i + ++i;
 
and does not depend on the order of calculating subexpression.
 
After the first decrement the side effect has to be applied. As lvalue was changed the new value of the lvalue has to be reread (or read) in the second expression. It is the meaning of applying of side effects. Then again the second expression is decremented and its side effect shall be applied before operator -. The operator shall use the last value of the lvaule.

Again I ask:  where in the standard can we find this wording?

Richard Smith

unread,
Aug 6, 2013, 3:22:31 PM8/6/13
to std-dis...@isocpp.org
On Tue, Aug 6, 2013 at 11:12 AM, Vlad from Moscow <vlad....@mail.ru> wrote:
This is totally the same as
 
int s = ++i + ++i;
 
and does not depend on the order of calculating subexpression.

That's not true. That initializer could evaluate as:

1) increment i on LHS
2) increment i on RHS
3) perform lvalue-to-rvalue conversion on LHS
4) perform lvalue-to-rvalue conversion on RHS
5) add (3) and (4)

That is, both sides of the + can see the incremented value. Or, since it has undefined behavior, it could do anything else.

--

David Rodríguez Ibeas

unread,
Aug 6, 2013, 3:22:58 PM8/6/13
to std-dis...@isocpp.org
On Tue, Aug 6, 2013 at 2:12 PM, Vlad from Moscow <vlad....@mail.ru> wrote:
This is totally the same as
 
int s = ++i + ++i;
 
and does not depend on the order of calculating subexpression.
 
After the first decrement the side effect has to be applied. As lvalue was changed the new value of the lvalue has to be reread (or read) in the second expression. It is the meaning of applying of side effects. Then again the second expression is decremented and its side effect shall be applied before operator -. The operator shall use the last value of the lvaule.

I don't think this is necessarily the case, it would be if the operator was defined as 'int operator+(int const&, int const&)' but not if it was defined as 'int operator+(int,int)' (which I believe is the case, but I have not been able to support/invalidate this). If it is indeed 'int +(int,int)', then there are two implicit lvalue-to-rvalue conversions that are not sequenced, and the set of possible outcomes for '++i + --i' with i starting with value 0 could be:

1 (++i, lvalue-to-rvalue conversion, --i, lvalue-to-rvalue conversion)
0 (++i,--1, lvalue-to-rvalue conversion, lvalue-to-rvalue conversion; conversely --i,++i followed by 2 conversions)
-1 (--i, lvalue-to-rvalue conversion, ++i, lvalue-to-rvalue conversion)


Reply all
Reply to author
Forward
0 new messages