x=x*x vs. i=i++

P

peter koch

(e-mail address removed) skrev:
why is i=i++ undefined while x=x*x is alright?

Because i=i++ contains to assignments to i. x=x*x only contains one
assignment to x.
It is when the same variable has two assignments without an intervening
sequenceproblem, you get into troubles.

Peter
 
M

Mark P

peter said:
(e-mail address removed) skrev:


Because i=i++ contains to assignments to i. x=x*x only contains one
assignment to x.
It is when the same variable has two assignments without an intervening
sequenceproblem, you get into troubles.

Peter

Out of curiousity, what about i = ++i? In this case it at least seems
that both assignments do the same thing.
 
C

Clark S. Cox III

Out of curiousity, what about i = ++i? In this case it at least seems
that both assignments do the same thing.

It doesn't matter if they "do the same thing". The fact that there are
two of them makes it undefined behavior.
 
C

CodeCracker

I think that in case of
i = i++ the problem is when to assign the incremented value of i to i.
Just for clarity if I define i on the left of equality as Li and on the
right of equality as Ri and rewrite the statement then
Li = Ri++;
This line will be executed as follows:
a. Get the value of Ri.
b. Should I assign the output of ++ operator on Ri now?
c. Assign Ri to Li
d. Or should I assign the incremented value of Ri to Ri now?
Since the C++ standard is not clear on this compiler author can
implement it in either of two ways and consequently the difference in
output is possible.
But if I write
Li = ++Ri;
then the intention is very clear. The steps in this case will be
a. Increment Ri
b. Get the value of incremented Ri
c: assign this new value of Ri to Li

I don't think there will be any problem in this second case.
 
A

AnalogFile

CodeCracker said:
I think that in case of
i = i++ the problem is when to assign the incremented value of i to i.
Just for clarity if I define i on the left of equality as Li and on the
right of equality as Ri and rewrite the statement then
Li = Ri++;
This line will be executed as follows:
a. Get the value of Ri.
b. Should I assign the output of ++ operator on Ri now?
c. Assign Ri to Li
d. Or should I assign the incremented value of Ri to Ri now?
Since the C++ standard is not clear on this compiler author can
implement it in either of two ways and consequently the difference in
output is possible.
But if I write
Li = ++Ri;
then the intention is very clear. The steps in this case will be
a. Increment Ri
b. Get the value of incremented Ri
c: assign this new value of Ri to Li

I don't think there will be any problem in this second case.

What you think is not really relevant.

#include <iostream>
#include <ostream>

int main()
{
int i=1;
i=++i;
std::cout << i;
}

if you compile and execute and it outputs 42 the compiler is not broken
and is behaving according to the standard.
 
H

hnaik

I think because:

i++ means i += 1
there is already an assignment
whereas:
x*x is just an expression.
 
G

Gavin Deane

CodeCracker said:
I think that in case of
i = i++ the problem is when to assign the incremented value of i to i.
Just for clarity if I define i on the left of equality as Li and on the
right of equality as Ri and rewrite the statement then
Li = Ri++;
This line will be executed as follows:
a. Get the value of Ri.
b. Should I assign the output of ++ operator on Ri now?
c. Assign Ri to Li
d. Or should I assign the incremented value of Ri to Ri now?
Since the C++ standard is not clear on this compiler author can
implement it in either of two ways and consequently the difference in
output is possible.

The C++ standard is perfectly clear. Modifying a value more than once
between sequence points gives undefined behaviour. The compiler could
implement it in either of the two ways you suggest. Or the compiler
could do absolutely anything else it likes.
But if I write
Li = ++Ri;
then the intention is very clear. The steps in this case will be
a. Increment Ri
b. Get the value of incremented Ri
c: assign this new value of Ri to Li

Why do you think those will be the steps, rather than, for eaxmple:

a. Evaluate the expression ++Ri (the value will be Ri + 1)
b. Should I assign the value of the expression ++Ri to Ri now?
c. Assign Ri to Li, but what is the value of Ri?
d. Or should I assign the value of the expression ++Ri to Ri now?
I don't think there will be any problem in this second case.

There is exactly the same problem with the second case as with the
first. Undefined behaviour.

Gavin Deane
 
P

Pete Becker

CodeCracker said:
Since the C++ standard is not clear on this compiler author can
implement it in either of two ways and consequently the difference in
output is possible.

The C++ Standard is quite clear: the behavior of that code is undefined.
That means that the standard does not require any particular behavior
from that code. It's certainly reasonable for a compiler to do what you
suggest, but unless the compiler's documentation tells you that that's
what it does or you've tested it, you're just speculating.
 
S

serghei.karoly

There is no way that a serious c++ compiler could generate a code wich
output is 42, I'm using GCC 3.4.4 and the output is 2.
 
G

Gavin Deane

There is no way that a serious c++ compiler could generate a code wich
output is 42, I'm using GCC 3.4.4 and the output is 2.

I think you missed the point.

Given this program

#include <iostream>
#include <ostream>

int main()
{
int i=1;
i=++i;
std::cout << i;
}

42 might be a less *likely* output than 2. But the point is that 42 is
just as *valid* as 2. Any output is as valid as any other. It is
unfortunate that sometimes when you invoke undefined behaviour, you see
exactly the effect you were expecting.

Gavin Deane
 
R

Richard Herring

There is no way that a serious c++ compiler could generate a code wich
output is 42,

A truly serious C++ compiler would refuse to compile such abominations
in the first place.
I'm using GCC 3.4.4 and the output is 2.

So what? According to the C++ standard it's at liberty to produce any
effects it likes.
 
P

Pete Becker

Gavin said:
42 might be a less *likely* output than 2. But the point is that 42 is
just as *valid* as 2.

It's valid according to the language definition. In fact, a compiler
will produce one of the two results that have been mentioned. The reason
the standard doesn't require one or the other is that this provision
applies to any code that modifies the same value more than once between
sequence points, so it's hard to write an exact specification of the
possible results. Aside from whether it is well-defined, either in
theory or in practice, though, this code is nonsense. Even if it were
well defined it has no reason to exist.
 
G

Gernot Frisch

There is no way that a serious c++ compiler could generate a code
wich
output is 42, I'm using GCC 3.4.4 and the output is 2.

LOL! If I were to write one, it would!
 
A

AnalogFile

There is no way that a serious c++ compiler could generate a code wich
output is 42, I'm using GCC 3.4.4 and the output is 2.

That's why Deep Thought will not be compiled with version 3.4.4.

When the ever increasing compilation times of GCC will top 7.5 million
years, it will.
 
G

Gernot Frisch

AnalogFile said:
That's why Deep Thought will not be compiled with version 3.4.4.

When the ever increasing compilation times of GCC will top 7.5
million years, it will.

This is one of the world-wide known jokes - long before the internet.
 
A

AnalogFile

Gernot said:
This is one of the world-wide known jokes - long before the internet.

Did not mean to be original.
But suspect serghei didn't actually recognize the philosophical
implications of my example (I know you did, from your earlier reply).
I just wanted to give him more keywords to google for.

oh, wait!
You actually mean GCC was faster in pre internet? ;-)
 
J

john_bode

CodeCracker said:
I think that in case of
i = i++ the problem is when to assign the incremented value of i to i.
Just for clarity if I define i on the left of equality as Li and on the
right of equality as Ri and rewrite the statement then
Li = Ri++;
This line will be executed as follows:
a. Get the value of Ri.
b. Should I assign the output of ++ operator on Ri now?
c. Assign Ri to Li
d. Or should I assign the incremented value of Ri to Ri now?
Since the C++ standard is not clear on this compiler author can
implement it in either of two ways and consequently the difference in
output is possible.
But if I write
Li = ++Ri;
then the intention is very clear. The steps in this case will be
a. Increment Ri
b. Get the value of incremented Ri
c: assign this new value of Ri to Li

Not quite. Here are the semantics for the pre- and postincrement
operators as applied to scalar types:

i++: evaluate to i, and sometime before the next sequence point,
increment i.
++i: evaluate to i+1, and sometime before the next sequence point,
increment i.

You can't make any assumptions about when the side effect is actually
applied, other than it must be before the next sequence point. The
second case can evaluate as

tmp <- Ri + 1
Ri <- Ri + 1
Li <- tmp

or

tmp <- Ri + 1
Li <- tmp
Ri <- Ri + 1

or

Ri <- Ri + 1
Li <- Ri

or even something else entirely, as long as the semantics are
preserved.
I don't think there will be any problem in this second case.

The second case has the exact same problem as the first case, at least
if you're dealing with scalar types. "i = ++i" is just as undefined as
"i = i++".
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top