i = v[i++] results in undefined behavior. Can't understand why.

A

Armen Tsirunyan

Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Thank you in advance,
Armen Tsirunyan
 
A

Andreas Milton M

Hello,

as far as I know a temporary object will be involved when the statement
is evaluated. Let's call it tmp. Semantically two different thing could
happen. See below.

Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

First evaluation order
tmp := v ; increment i ; i := tmp.

Second evalutaion order:
tmp := v ; i:= tmp ; increment i;

In the first case we gain i+1 := v, whereas in the second case we
gain i = v[i+1].

Yours,
Andreas
 
J

Johannes Schaub (litb)

Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i = i
+ 1))" you will not have two unsequenced side effects anymore, because the
assignment in "i = i + 1" is sequenced before the assignment in "i = *(...".
BUT you still have the same value computation be unsequenced to the same
side effect as in your snippet. So for both the pre and postfix version you
have undefined behavior.
 
A

Andreas Milton M

Hello,

As far as I know during the evaluation of "i = v[i++]" two semantically
different things could happen. It is easier to see that by replacing the
the =-operator by a pseudo-code function assign(x,y) which realizes x = y.

First evaluation of assign(i, v[i++]):

Evaluate i, then add v[i++] to i.
We gain i := 1 + v

Second evaluation of assign(i, v[i++]):
Evaluate i++, then evaluate i, evaluate v

The side-effect modifies i before we evaluate the index operator.
Then we gain i = v[i+1]

The order of expression evaluation is not uniquely determined. I think
this is what the phrase you cite from clause 1.9 paragraph 15 (n3092)
is about:

"Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced. "

(unsequenced = order not uniquely specified)

Yours,
Andreas
 
A

Armen Tsirunyan

Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).

Thanks, I understand this now.
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

But I don't understand this, is there a value computation of the left
i here? I mean an lvalue is expected here, which as I understand
means the object not the value. I mean this is rather an object
identification rather than value computation. Is there a more formal
definition of what a value computation is and what a side effect on an
object is?
 
A

Andreas Milton M

Hello,

As far as I know during the evaluation of "i = v[i++]" two semantically
different things could happen. It is easier to see that by replacing the
the =-operator by a pseudo-code function assign(x,y) which realizes x = y.

First evaluation of assign(i, v[i++]):

Evaluate i, then associate v[i++] to i.
We gain i := 1 + v

Second evaluation of assign(i, v[i++]):
Evaluate i++, then evaluate i, evaluate v

The side-effect modifies i before we evaluate the index operator.
Then we gain i = v[i+1]

The order of expression evaluation is not uniquely determined. I think
this is what the phrase you cite from clause 1.9 paragraph 15 (n3092)
is about:

"Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced. "

(unsequenced = order not uniquely specified)

Yours,
Andreas
 
A

Armen Tsirunyan

Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i = i
+ 1))" you will not have two unsequenced side effects anymore, because the
assignment in "i = i + 1" is sequenced before the assignment in "i = *(...".
BUT you still have the same value computation be unsequenced to the same
side effect as in your snippet. So for both the pre and postfix version you
have undefined behavior.

If I may quote you from another thread :)
Please disregard the last one. That's still undefined in C++0x it seems.
Value computation of the left i is not sequenced relative to the side effect
of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?
 
J

Johannes Schaub (litb)

Armen said:
Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).

Thanks, I understand this now.
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

But I don't understand this, is there a value computation of the left
i here? I mean an lvalue is expected here, which as I understand
means the object not the value. I mean this is rather an object
identification rather than value computation. Is there a more formal
definition of what a value computation is and what a side effect on an
object is?

At 1.9/12 of n3126 it says

"Evaluation of an expression (or a sub-expression) in general includes both
value computations (including determining the identity of an object for
glvalue evaluation and fetching a value previously assigned to an object for
prvalue evaluation) and initiation of side effects."
 
J

Johannes Schaub (litb)

Armen said:
Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i =
i + 1))" you will not have two unsequenced side effects anymore, because
the assignment in "i = i + 1" is sequenced before the assignment in "i =
*(...". BUT you still have the same value computation be unsequenced to
the same side effect as in your snippet. So for both the pre and postfix
version you have undefined behavior.

If I may quote you from another thread :)
Please disregard the last one. That's still undefined in C++0x it seems.
Value computation of the left i is not sequenced relative to the side
effect of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

++i is

i = i + 1

The Standard says for postfix i++:

"The value computation of the ++ expression is sequenced before the
modification of the operand object."

And it says for i = x

"In all cases, the assignment is sequenced after the value computation of
the right and left operands, and before the value computation of the
assignment expression."

Together this means that all side effects are sequenced and all side effects
are sequenced relative to all value computations. Thus the behavior of
"(++i)++" is defined.
 
A

Armen Tsirunyan

Armen said:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined..
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?
Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Thanks, I understand this now.
But I don't understand this, is there a value computation of the left
i here? I mean an lvalue is expected here, which as I understand
means the object not the value. I mean this is rather an object
identification rather than value computation. Is there a more formal
definition of what a value computation is and what a side effect on an
object is?

At 1.9/12 of n3126 it says

"Evaluation of an expression (or a sub-expression) in general includes both
value computations (including determining the identity of an object for
glvalue evaluation and fetching a value previously assigned to an object for
prvalue evaluation) and initiation of side effects."

so, the incrementation of i in i++ is a side effect, whereas the
incrementation of i in ++i is a part of value computation, and
therefore makes ++++i defined. Is that correct?
 
A

Andreas Milton M

Hello,

To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
|
brackets
|
post-increment
|
i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas


Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i = i
+ 1))" you will not have two unsequenced side effects anymore, because the
assignment in "i = i + 1" is sequenced before the assignment in "i = *(...".
BUT you still have the same value computation be unsequenced to the same
side effect as in your snippet. So for both the pre and postfix version you
have undefined behavior.

If I may quote you from another thread :)
Please disregard the last one. That's still undefined in C++0x it seems.
Value computation of the left i is not sequenced relative to the side effect
of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?
 
A

Andreas Milton M

Hello,

You say in your reply that ++(i++) shoould not be well-defined. I don't
think that's right. please see below.



Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i = i
+ 1))" you will not have two unsequenced side effects anymore, because the
assignment in "i = i + 1" is sequenced before the assignment in "i = *(...".
BUT you still have the same value computation be unsequenced to the same
side effect as in your snippet. So for both the pre and postfix version you
have undefined behavior.

If I may quote you from another thread :)
Please disregard the last one. That's still undefined in C++0x it seems.
Value computation of the left i is not sequenced relative to the side effect
of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?


To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
|
brackets
|
post-increment
|
i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas
 
A

Armen Tsirunyan

Hello,

To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
   |
brackets
   |
post-increment
   |
   i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas

Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator"..
So how come is this undefined behavior?
Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").
If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i = i
+ 1))" you will not have two unsequenced side effects anymore, because the
assignment in "i = i + 1" is sequenced before the assignment in "i = *(...".
BUT you still have the same value computation be unsequenced to the same
side effect as in your snippet. So for both the pre and postfix version you
have undefined behavior.
If I may quote you from another thread :)
i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

I wrote (++i)++, not ++(i++), which would be afaik ill-formed since i+
+ is a prvalue. Also I thought that parentheses do notcontribute to
the order of evaluation of operands or their sequencing, rather, they
specify the composition tree of the subexpressions in an expression. I
am so confused right now :)
 
J

Johannes Schaub (litb)

Johannes said:
Armen said:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of
its subexpressions need not be
performed consistently in different evaluations. —end note ] The value
computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by 1
is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the operator".
So how come is this undefined behavior?

Because value computations do not include side effects. So you have two
unsequenced side effects in your snippet (the increment and assignment).
Moreover you have a value computation on i (left i) that is unsequenced
relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v + (i
= i + 1))" you will not have two unsequenced side effects anymore,
because the assignment in "i = i + 1" is sequenced before the assignment
in "i = *(...". BUT you still have the same value computation be
unsequenced to the same side effect as in your snippet. So for both the
pre and postfix version you have undefined behavior.

If I may quote you from another thread :)
++i = 0; // defined by c++0x, undefined by C++03
++ ++i; // defined by c++0x, undefined by C++03
i = ++i; // defined by c++0x, undefined by C++03

Please disregard the last one. That's still undefined in C++0x it seems.
Value computation of the left i is not sequenced relative to the side
effect of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

++i is

i = i + 1

The Standard says for postfix i++:

"The value computation of the ++ expression is sequenced before the
modification of the operand object."

And it says for i = x

"In all cases, the assignment is sequenced after the value computation of
the right and left operands, and before the value computation of the
assignment expression."

Together this means that all side effects are sequenced and all side
effects are sequenced relative to all value computations. Thus the
behavior of "(++i)++" is defined.

I suspect you will also need the one you quoted to really nail it down: "The
value computations of the operands of an operator are sequenced before the
value computation of the result of the operator.". So in the end, I think
the defined order is

glvalue evaluation of i
assignment to i
glvalue evaluation of i
prvalue evaluation of i
increment of i
 
J

Johannes Schaub (litb)

Armen said:
Hello,

To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
|
brackets
|
post-increment
|
i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas

On Sep 26, 10:00 pm, "Johannes Schaub (litb)"<[email protected]>
wrote:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations
of its subexpressions need not be
performed consistently in different evaluations. —end note ] The
value computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by
1 is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the
operator". So how come is this undefined behavior?
Because value computations do not include side effects. So you have
two unsequenced side effects in your snippet (the increment and
assignment). Moreover you have a value computation on i (left i) that
is unsequenced relative to a side effect on i (the right "i++").
If you write this as "i = v[++i]", which is equivalent to "i = *(v +
(i = i + 1))" you will not have two unsequenced side effects anymore,
because the assignment in "i = i + 1" is sequenced before the
assignment in "i = *(...". BUT you still have the same value
computation be unsequenced to the same side effect as in your snippet.
So for both the pre and postfix version you have undefined behavior.
If I may quote you from another thread :)
++i = 0; // defined by c++0x, undefined by C++03
++ ++i; // defined by c++0x, undefined by C++03
i = ++i; // defined by c++0x, undefined by C++03
Please disregard the last one. That's still undefined in C++0x it
seems. Value computation of the left i is not sequenced relative to
the side effect of "++i".
i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

I wrote (++i)++, not ++(i++), which would be afaik ill-formed since i+
+ is a prvalue. Also I thought that parentheses do notcontribute to
the order of evaluation of operands or their sequencing, rather, they
specify the composition tree of the subexpressions in an expression. I
am so confused right now :)

I agree with you on this.
 
J

Johannes Schaub (litb)

Armen said:
Armen said:
On Sep 26, 10:00 pm, "Johannes Schaub (litb)" <[email protected]>
wrote:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations
of its subexpressions need not be
performed consistently in different evaluations. —end note ] The
value computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is
undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented by
1 is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the
operator". So how come is this undefined behavior?
Because value computations do not include side effects. So you have
two unsequenced side effects in your snippet (the increment and
assignment).
Thanks, I understand this now.
Moreover you have a value computation on i (left i) that is
unsequenced relative to a side effect on i (the right "i++").
But I don't understand this, is there a value computation of the left
i here? I mean an lvalue is expected here, which as I understand
means the object not the value. I mean this is rather an object
identification rather than value computation. Is there a more formal
definition of what a value computation is and what a side effect on an
object is?

At 1.9/12 of n3126 it says

"Evaluation of an expression (or a sub-expression) in general includes
both value computations (including determining the identity of an object
for glvalue evaluation and fetching a value previously assigned to an
object for prvalue evaluation) and initiation of side effects."

so, the incrementation of i in i++ is a side effect, whereas the
incrementation of i in ++i is a part of value computation, and
therefore makes ++++i defined. Is that correct?

The increment is not part of value computation. But it is sequenced before a
value computation and after a value computation since ++i is equivalent to
i+=1 (which is equivalent to "i = i + 1" except that i is only evaluated
once as the lhs). So you have a sequence of

glvalue computation
increment
glvalue computation
increment
glvalue computation
.....

For "++ ... ++ i;" .
 
A

Andreas Milton M

Armen said:
Hello,

To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
|
brackets
|
post-increment
|
i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas

On 09/26/2010 07:46 PM, Armen Tsirunyan wrote:



On Sep 26, 10:00 pm, "Johannes Schaub (litb)"<[email protected]>
wrote:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations
of its subexpressions need not be
performed consistently in different evaluations. —end note ] The
value computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by
1 is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the
operator". So how come is this undefined behavior?

Because value computations do not include side effects. So you have
two unsequenced side effects in your snippet (the increment and
assignment). Moreover you have a value computation on i (left i) that
is unsequenced relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v +
(i = i + 1))" you will not have two unsequenced side effects anymore,
because the assignment in "i = i + 1" is sequenced before the
assignment in "i = *(...". BUT you still have the same value
computation be unsequenced to the same side effect as in your snippet.
So for both the pre and postfix version you have undefined behavior.

If I may quote you from another thread :)
++i = 0; // defined by c++0x, undefined by C++03
++ ++i; // defined by c++0x, undefined by C++03
i = ++i; // defined by c++0x, undefined by C++03

Please disregard the last one. That's still undefined in C++0x it
seems. Value computation of the left i is not sequenced relative to
the side effect of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

I wrote (++i)++, not ++(i++), which would be afaik ill-formed since i+
+ is a prvalue. Also I thought that parentheses do notcontribute to
the order of evaluation of operands or their sequencing, rather, they
specify the composition tree of the subexpressions in an expression. I
am so confused right now :)

I agree with you on this.

I'm confused now too, so I'm not quite sure on what we agree or
disagree. But I'll try to restate my argument in a different shape so
that you can agree with it or find the mistake.

Any expression has a unique syntax tree. In order to evaluate one node
in the tree we need to evaluate all of its children first. The order by
which we evaluate the subexpressions is unspecified however.
A side-effect like i++ is not visible at the place where we evaluate the
expression i++ but at the next time we are confronted with the leaf i in
the syntax tree. If the next position where we meet i in the syntax tree
is uniquely specified by the structure of the tree, we have no ambiguity
problem, otherwise we do.

Let expr be an expression, then by the grammar of c++ the expression
(expr) is an expression too. There expression trees must be different,
otherwise expr and (expr) would be the same expression.
The expression tree is a subtree of (expr)

We have an expression tree for expr, call it T_expr.

The expression tree for (expr) is the tree
()
|
expr

You have three choices:
1) Find the mistake
2) accept it.
3) or, if it's giving you too much of a headache, like side-effects
always do, ignore it :)

Cheers,
Andreas
 
A

Andreas Milton M

Armen said:
Hello,

To my knowledge the above ++(i++) expression is absolutely well-defined
since the brackets enforce uniqueness.
C++ as any language guarantees that subexpressions of an expression are
evaluated before the expression itself is evaulated. Ambiguities only
arise in the order of the evaluations of subexpressions, which are
unsequenced (=unspecified) in C++ for good reason. But here the bracket
inforces uniqueness. The brackets can be understood as a unary operator.

We would get the following syntax tree:

pre-increment
|
brackets
|
post-increment
|
i

Where is the ambiguity? I don't see any, albeit the expression is ugly
of course. Even if we take out the brackets the expression would be
unique, since right increments have higher priority than left increments.

Cheers,
Andreas

On 09/26/2010 07:46 PM, Armen Tsirunyan wrote:



On Sep 26, 10:00 pm, "Johannes Schaub (litb)"<[email protected]>
wrote:
Armen Tsirunyan wrote:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations
of its subexpressions need not be
performed consistently in different evaluations. —end note ] The
value computations of the operands of an
operator are sequenced before the value computation of the result of
the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the
same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
[ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]

let's consider i = v[i++]. the side effect of i being incremented by
1 is SEQUENCED before the side effect of i being assigned v[i++],
because "The value computations of the operands of an operator are
sequenced before the value computation of the result of the
operator". So how come is this undefined behavior?

Because value computations do not include side effects. So you have
two unsequenced side effects in your snippet (the increment and
assignment). Moreover you have a value computation on i (left i) that
is unsequenced relative to a side effect on i (the right "i++").

If you write this as "i = v[++i]", which is equivalent to "i = *(v +
(i = i + 1))" you will not have two unsequenced side effects anymore,
because the assignment in "i = i + 1" is sequenced before the
assignment in "i = *(...". BUT you still have the same value
computation be unsequenced to the same side effect as in your snippet.
So for both the pre and postfix version you have undefined behavior.

If I may quote you from another thread :)
++i = 0; // defined by c++0x, undefined by C++03
++ ++i; // defined by c++0x, undefined by C++03
i = ++i; // defined by c++0x, undefined by C++03

Please disregard the last one. That's still undefined in C++0x it
seems. Value computation of the left i is not sequenced relative to
the side effect of "++i".

i = ++i; whether or not this is defined depends pretty much on what a
value computation means.
Also, is
(++i)++;
defined?
I guess not, am I right?

I wrote (++i)++, not ++(i++), which would be afaik ill-formed since i+
+ is a prvalue. Also I thought that parentheses do notcontribute to
the order of evaluation of operands or their sequencing, rather, they
specify the composition tree of the subexpressions in an expression. I
am so confused right now :)

I agree with you on this.

You're right. I agree now too.
 
B

Bo Persson

Armen said:
Armen said:
Please help me, I just can't understand this.
Clause 1.9 Paragraph 15 (n3092) says:
Except where noted, evaluations of operands of individual
operators and of subexpressions of individual
expressions are unsequenced. [ Note: In an expression that is
evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced
evaluations of its subexpressions need not be
performed consistently in different evaluations. —end note ] The
value computations of the operands of an
operator are sequenced before the value computation of the result
of the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on
the same scalar object or a value computation
using the value of the same scalar object, the behavior is
undefined. [ Example:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}
—end example ]
let's consider i = v[i++]. the side effect of i being incremented
by 1 is SEQUENCED before the side effect of i being assigned
v[i++], because "The value computations of the operands of an
operator are sequenced before the value computation of the result
of the operator". So how come is this undefined behavior?

Because value computations do not include side effects. So you
have two unsequenced side effects in your snippet (the increment
and assignment).

Thanks, I understand this now.
Moreover you have a value computation on i (left i) that is
unsequenced relative to a side effect on i (the right "i++").

But I don't understand this, is there a value computation of the
left i here? I mean an lvalue is expected here, which as I
understand means the object not the value. I mean this is rather an
object identification rather than value computation. Is there a
more formal definition of what a value computation is and what a
side effect on an object is?

You have two side effects here, storing the result of i++ and storing
the result of the assignment to i. The fact that they are both
performed without an intervening sequence point is what causes the
undefined behavior.

My understanding is that the committee knows about hardware where this
actually doesn't work, so they defined the language accordingly.



Bo Persson
 
J

James Kanze

Armen Tsirunyan wrote:

[...]
It means what it says: the computation of the *value* of the
expression, without any side effects.
i = i + 1
The Standard says for postfix i++:
"The value computation of the ++ expression is sequenced before the
modification of the operand object."
And it says for i = x
"In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the
value computation of the assignment expression."
Together this means that all side effects are sequenced and
all side effects are sequenced relative to all value
computations. Thus the behavior of "(++i)++" is defined.

Where do you get that from? The sentences you quote only speak
of sequencing the *value* computation. Nothing about side
effects.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top