469,934 Members | 2,513 Online

# Is this an ambiguity in the C++ standard?

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

Oct 18 '05 #1
14 1461
<Cl*********@yahoo.com> wrote in message
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
Oct 18 '05 #2
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.

Oct 18 '05 #3

Mike Wahler wrote:
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>
http://www.open-std.org/jtc1/sc22/wg...fects.html#351

Regards,
Sumit.

Oct 18 '05 #4
Cl*********@yahoo.com wrote:
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

Oct 18 '05 #5

Cl*********@yahoo.com wrote:
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.

http://www.angelikalanger.com/Articl...ncePoints.html

Regards,
Sumit.

Oct 18 '05 #6
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. =)

Oct 18 '05 #7

Cl*********@yahoo.com wrote:
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 ?

Oct 18 '05 #8
Geo wrote:

Cl*********@yahoo.com wrote:
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 ?

Well, if the teacher achieves that effect by being (partially) incorrect,
misleading, incoherent, flaky, ...; then the one that at least makes you
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
Oct 18 '05 #9

"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:dj**********@murdoch.acc.Virginia.EDU...
Cl*********@yahoo.com wrote:
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.

Technically I believe it's Unspecified, not Undefined. Meaning it better not
format my disks, because that would be undefined behavior.
Oct 19 '05 #10
Jim Langston wrote:

"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:dj**********@murdoch.acc.Virginia.EDU...
Cl*********@yahoo.com 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].
Best

Kai-Uwe Bux
Oct 19 '05 #11

"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:dj**********@murdoch.acc.Virginia.EDU...
Jim Langston wrote:

"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:dj**********@murdoch.acc.Virginia.EDU...
Cl*********@yahoo.com 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.
Oct 19 '05 #12

Jim Langston wrote:
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/wg...fects.html#351

Regards,
Sumit.

Oct 19 '05 #13
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

Oct 19 '05 #14
In article <dj**********@murdoch.acc.Virginia.EDU>,
Kai-Uwe Bux <jk********@gmx.net> wrote:
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
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Oct 19 '05 #15

### This discussion thread is closed

Replies have been disabled for this discussion.