user388338
user388338

Reputation: 777

Is the behaviour of i = i++ really undefined?

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

According to c++ standard,

i = 3;
i = i++;

will result in undefined behavior.

We use the term "undefined behavior" if it can lead to more then one result. But here, the final value of i will be 4 no matter what the order of evaluation, so shouldn't this really be called "unspecified behavior"?

Upvotes: 22

Views: 16303

Answers (9)

Ted
Ted

Reputation: 101

This question is old, but still appears to be referenced frequently, so it deserves a new answer in light of changes to the standard, from C++17.

expr.ass Subclause 1 explains

... the assignment is sequenced after the value computation of the right and left operands ...

and

The right operand is sequenced before the left operand.

The implication here is that the side-effects of the right operand are sequenced before the assignment, which means that the expression is not addressed by the provision in [basic.exec] Subclause 10:

If a side effect on a memory location ([intro.memory]) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined

The behavior is defined, as explained in the example which immediately follows.

See also: What made i = i++ + 1; legal in C++17?

Upvotes: 8

Damian K.
Damian K.

Reputation: 333

I saw such question at OCAJP practice test. IntelliJ's IDEA decompiler turns this

public static int iplus(){
    int i=0;
    return i=i++;
}

into this

public static int iplus() {
    int i = 0;
    byte var10000 = i;
    int var1 = i + 1;
    return var10000;
}

Create JAR from module, then import as library & inspect. enter image description here

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320361

No, we don't use the term "undefined behavior" when it can simply lead to more than one arithmetical result. When the behavior is limited to different arithmetical results (or, more generally, to some set of predictable results), it is typically referred to as unspecified behavior.

Undefined behavior means completely unpredictable and unlimited consequences, like formatting the hard drive on your computer or simply making your program to crash. And i = i++ is undefined behavior.

Where you got the idea that i should be 4 in this case is not clear. There's absolutely nothing in C++ language that would let you come to that conclusion.

Upvotes: 10

Marcelo Cantos
Marcelo Cantos

Reputation: 185852

The phrase, "…the final value of i will be 4 no matter what the order of evaluation…" is incorrect. The compiler could emit the equivalent of this:

i = 3;
int tmp = i;
++i;
i = tmp;

or this:

i = 3;
++i;
i = i - 1;

or this:

i = 3;
i = i;
++i;

As to the definitions of terms, if the answer was guaranteed to be 4, that wouldn't be unspecified or undefined behavior, it would be defined behavior.

As it stands, it is undefined behaviour according to the standard (Wikipedia), so it's even free to do this:

i = 3;
system("sudo rm -rf /"); // DO NOT TRY THIS AT HOME … OR AT WORK … OR ANYWHERE.

Upvotes: 30

hlovdal
hlovdal

Reputation: 28180

In C and also in C++, the order of any operation between two sequence points is completely up to the compiler and cannot be dependent on. The standard defines a list of things that makes up sequence points, from memory this is

  1. the semicolon after a statement
  2. the comma operator
  3. evaluation of all function arguments before the call to the function
  4. the && and || operand

Looking up the page on wikipedia, the lists is more complete and describes more in detail. Sequence points is an extremely important concept and if you do not already know what it means, you will benefit greatly by learning it right away.

Upvotes: 6

Guffa
Guffa

Reputation: 700152

1. No, the result will be different depending on the order of evaluation. There is no evaluation boundary between the increment and the assignment, so the increment can be performed before or after the assignment. Consider this behaviour:

load i into CX
copy CX to DX
increase DX
store DX in i
store CX in i

The result is that i contains 3, not 4.

As a comparison, in C# there is a evaluation boundary between the evaulation of the expression and the assignment, so the result will always be 3.

2. Even if the exact behaviour isn't specified, the specification is very clear on what it covers and what it doesn't cover. The behaviour is specified as undefined, it's not unspecified.

Upvotes: 5

Chris
Chris

Reputation: 515

It's not worth it to type i=i++ when you could simply type i++.

Upvotes: 0

Chris Becke
Chris Becke

Reputation: 36016

i=, and i++ are both side effects that modify i.

i++ does not imply that i is only incremented after the entire statement is evaluated, merely that the current value of i has been read. As such, the assignment, and the increment, could happen in any order.

Upvotes: 4

Pablo Santa Cruz
Pablo Santa Cruz

Reputation: 181270

To answer your questions:

  1. I think "undefined behavior" means that the compiler/language implementator is free to do whatever it thinks best, and no that it could lead to more than one result.
  2. Because it's not unspecified. It's clearly specified that its behavior is undefined.

Upvotes: 2

Related Questions