Is this an ambiguity in the C++ standard?

C

Clay_Culver

My professor claims that this code:
int f()
{
int x = 5;
int &y = x;
x += ++y;

return x;
}

Can return either 11 (if y is moved into a register, incremented, x is
moved into a seperate register, then x=x+y is performed, resulting in
x=5+6=11) or 12 as we would expect (since x and y refer to the same
location the compiler should only move it into a register once
resulting in x=5+1, then x=6+6=12).

Now in order for this to be a problem (for it to ever possibly be 11),
the compiler would have to be braindead. However, does anyone know if
this actually goes against the C++ standards in any way to implement
the compiler such that f() results in 11 instead of 12? And can anyone
point out that relevant section in the standards?

I'm not looking for an explination that this could never happen in
practice (I already know this). I really have to find out if this goes
against the C++ standards, because it's the only way I can argue back
points on this issue.

Thanks!
Clay
 
K

Kai-Uwe Bux

My professor claims that this code:
int f()
{
int x = 5;
int &y = x;
x += ++y;

return x;
}

Can return either 11 (if y is moved into a register, incremented, x is
moved into a seperate register, then x=x+y is performed, resulting in
x=5+6=11) or 12 as we would expect (since x and y refer to the same
location the compiler should only move it into a register once
resulting in x=5+1, then x=6+6=12).

Now in order for this to be a problem (for it to ever possibly be 11),
the compiler would have to be braindead. However, does anyone know if
this actually goes against the C++ standards in any way to implement
the compiler such that f() results in 11 instead of 12? And can anyone
point out that relevant section in the standards?

I'm not looking for an explination that this could never happen in
practice (I already know this). I really have to find out if this goes
against the C++ standards, because it's the only way I can argue back
points on this issue.

Your professor is more correct than you. In fact, the behavior of the
program is undefined, i.e., anything could happen including but not limited
to returning 12 or formatting all disks and not returning at all.

You will want to read up on sequence points. The FAQ item 39.15 might be a
good start.


Best

Kai-Uwe Bux
 
M

Mike Wahler

My professor claims that this code:
int f()
{
int x = 5;
int &y = x;
x += ++y;

return x;
}

Can return either 11 (if y is moved into a register, incremented, x is
moved into a seperate register, then x=x+y is performed, resulting in
x=5+6=11) or 12 as we would expect (since x and y refer to the same
location the compiler should only move it into a register once
resulting in x=5+1, then x=6+6=12).

Or anything else can happen.

What a compiler might do, with or without registers,
is irrelevant. The behavior is undefined: an attempt
is made to modify an object more than once without
an intervening sequence point.

I don't have my copy of the standard handy, perhaps someone
else can quote chapter and verse.

-Mike
 
C

Clay_Culver

Your post gave me the correct terminology to google for. You can't
modify a variable more than once in a single statement in C or C++. I
didn't realize that was a no-no specified by the standard, but I
understand now.

Thanks.
 
S

Sumit Rajan

Mike said:
I don't have my copy of the standard handy, perhaps someone
else can quote chapter and verse.

5/4 of the Standard:

<QUOTE>
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.53) 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. [Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
-end example]


</QUOTE>


And also helpful is:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#351

Regards,
Sumit.
 
C

Clay_Culver

If he had simply told me it was undefined by the specification I
wouldn't have argued. He only said that it could have different
affects on different compilers, which made me very curious. =)
 
G

Geo

If he had simply told me it was undefined by the specification I
wouldn't have argued. He only said that it could have different
affects on different compilers, which made me very curious. =)

And which is better, the teacher that stuffs your brain full of facts
and rules, or the teacher that makes you think, reasearch and learn ?
 
K

Kai-Uwe Bux

Geo said:
And which is better, the teacher that stuffs your brain full of facts
and rules, or the teacher that makes you think, reasearch and learn ?

Well, if the teacher achieves that effect by being (partially) incorrect,
misleading, incoherent, flaky, ...; then the one that at least makes you
know the facts is clearly better. You might still learn more with the bad
teacher, it will just not be his achievement but yours only.

Also, what makes you think that a teacher who "stuffs your brain full of
facts and rules" does not "make you think, research and learn". My
experience is that knowing gazillions of facts and rules eases thinking,
research and learning quite tremendously. The more you know, the faster you
comprehend.


Best

Kai-Uwe Bux
 
J

Jim Langston

Kai-Uwe Bux said:
Your professor is more correct than you. In fact, the behavior of the
program is undefined, i.e., anything could happen including but not
limited
to returning 12 or formatting all disks and not returning at all.

Technically I believe it's Unspecified, not Undefined. Meaning it better not
format my disks, because that would be undefined behavior.
 
K

Kai-Uwe Bux

Jim said:
Kai-Uwe Bux said:
My professor claims that this code:
int f()
{
int x = 5;
int &y = x;
x += ++y;

return x;
}
[snip]
In fact, the behavior of the
program is undefined, i.e., anything could happen including but not
limited
to returning 12 or formatting all disks and not returning at all.

Technically I believe it's Unspecified, not Undefined. Meaning it better
not format my disks, because that would be undefined behavior.

I am not sure, but I thought there is a difference of built-in types like
int and user defined types that have operators defined. In the later case
an expression like (I am simplifying the example)

x += ++x

is equivalent to

operator+= ( x, operator++(x) );

or something involving member calls. In this case, the evaluation order is
unspecified as you say. However, note that there are gazillions of sequence
points in that line that come from passing arguments to function calls.

In the case of built in types there are no function calls implied and there
are no sequence points. There, the language of the standard is IIRC "the
program shall not [whatever]" which implies undefined behavior if the
program does [whatever].


Best

Kai-Uwe Bux
 
J

Jim Langston

Kai-Uwe Bux said:
Jim said:
Kai-Uwe Bux said:
(e-mail address removed) wrote:

My professor claims that this code:
int f()
{
int x = 5;
int &y = x;
x += ++y;

return x;
}
[snip]
In fact, the behavior of the
program is undefined, i.e., anything could happen including but not
limited
to returning 12 or formatting all disks and not returning at all.

Technically I believe it's Unspecified, not Undefined. Meaning it better
not format my disks, because that would be undefined behavior.

I am not sure, but I thought there is a difference of built-in types like
int and user defined types that have operators defined. In the later case
an expression like (I am simplifying the example)

x += ++x

is equivalent to

operator+= ( x, operator++(x) );

or something involving member calls. In this case, the evaluation order is
unspecified as you say. However, note that there are gazillions of
sequence
points in that line that come from passing arguments to function calls.

In the case of built in types there are no function calls implied and
there
are no sequence points. There, the language of the standard is IIRC "the
program shall not [whatever]" which implies undefined behavior if the
program does [whatever].

Partial repost of a quote from the standard (emphasis mine)

5/4 of the Standard:

<QUOTE>
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.*****53) 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. [Example:
i = v[i++]; // the behavior is ****unspecified****
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is ****unspecified****
i = i + 1; // the value of i is incremented
-end example]

(end quote)

The only part that is marked as undefined has to do with an expression not
matching the critera for which that paragraph was intended "for eacn
allowable ordering of the subexpressions of a full expression."

x += ++x;

seems, to me anyway, to strictly fall into that catagory, the order of the
subexpressions. So the final value of x would be unspecificed, not undfined
behavior, as I read this quote anyway. It doesn't seem to matter if the
variable in question is a built in or user defined type.
 
S

Sumit Rajan

Jim said:
Partial repost of a quote from the standard (emphasis mine)

5/4 of the Standard:

<QUOTE>
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.*****53) 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. [Example:
i = v[i++]; // the behavior is ****unspecified****
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is ****unspecified****
i = i + 1; // the value of i is incremented
-end example]


See:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#351

Regards,
Sumit.
 
K

Kai-Uwe Bux

Jim Langston wrote:

[snip]
Partial repost of a quote from the standard (emphasis mine)

5/4 of the Standard:

<QUOTE>
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.*****53) 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. [Example:
i = v[i++]; // the behavior is ****unspecified****
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is ****unspecified****
i = i + 1; // the value of i is incremented
-end example]

(end quote)

The only part that is marked as undefined has to do with an expression not
matching the critera for which that paragraph was intended "for eacn
allowable ordering of the subexpressions of a full expression."

x += ++x;

seems, to me anyway, to strictly fall into that catagory, the order of the
subexpressions. So the final value of x would be unspecificed, not
undfined
behavior, as I read this quote anyway.

I have a hard time understanding the wording of the standard (in particular
making sense of the examples given). What troubles me is the line:

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.
[...] otherwise the behavior is undefined.

Now consider

x += ++x;

One way to evaluate this is to compute ++x first. This modifies the value of
x and returns some value which then is used by += to modify x again. So,
how does that satisfy the requirements of the first sentence so that the
last does not imply undefined behavior?

[I agree that my reading should be wrong given the examples in the standard,
but I just cannot make any sense of those examples in light of the wording
above them.]


Best

Kai-Uwe Bux
 
G

Greg Comeau

I have a hard time understanding the wording of the standard (in particular
making sense of the examples given). What troubles me is the line:

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.
[...] otherwise the behavior is undefined.

Now consider

x += ++x;

One way to evaluate this is to compute ++x first.

Right, that's part of the problem, as it's one way to evaluate,
but in this case it matters because it's possible to produce
different results and...
This modifies the value of
x and returns some value which then is used by += to modify x again. So,
how does that satisfy the requirements of the first sentence so that the
last does not imply undefined behavior?

Since it is being requested get modified more than one, as in
your example, then it's un-behavior.
 

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
474,436
Messages
2,571,696
Members
48,796
Latest member
Greg L.
Top