21

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"?

mrflash818
  • 930
  • 13
  • 24
user388338
  • 729
  • 2
  • 6
  • 11

9 Answers9

30

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.
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • modded up in the hope that the OP will understand why the "end result" is in no way predictable even in a totally well-behaved interpretation of the standard (i.e. no monkeys or cheese). – Joris Timmermans Feb 11 '11 at 12:37
  • 2
    +5 for saying system("sudo rm -rf /"); – Destructor Feb 06 '16 at 16:51
  • 4
    `sudo rm -rf /` doesn't do anything on modern versions of `rm` where you need to add `--no-preserve-root` – cat Feb 17 '16 at 02:46
  • Why would the compiler ever "emit" the last one? The postfix operator (by my understanding) always "returns" the value prior to its operation...I agree to to say the OP is wrong to say the result will be 4....though your last scenario seems to suggest it could be (I mean if this is truly undefined I wouldn't question. I just don't see why it is myself...) – Assimilater Jun 28 '16 at 17:45
  • Found an answer here: http://stackoverflow.com/questions/4362501/any-good-reason-why-assignment-operator-isnt-a-sequence-point – Assimilater Jun 28 '16 at 18:13
10

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • If Java & C# can define behaviour of i=i++ then why C & C++ can't? – Destructor Feb 06 '16 at 16:30
  • 3
    @Pravasi Meet: Why would it want to? UB is a consequence of *freedom* deliberately introduced/left in language spec in order to facilitate various performance-related optimizations, up to saving specific CPU cycles. This makes sense in *native* machine code, which is what C and C++ are normally used for. Java was originally developed as a completely different platform (VM-based). On that virtual platform hunting specific CPU cycles in user-level code makes no sense, since the VM overhead is already much greater than that anyway. Under such circumstances, Java opted for stricter specification. – AnT stands with Russia Feb 06 '16 at 17:18
  • 2
    In other words, C/C++ and Java are very different platforms with very different sets of priorities, especially when it comes to low-level performance optimizations. – AnT stands with Russia Feb 06 '16 at 17:20
6

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.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
  • sir..i have read this..thats why i said its undefined according to the standard...but i am getting the reason why its undefined when the final value is independent of the order of evolution of operands – user388338 Feb 11 '11 at 12:27
  • My interpretation of the meaning of undefined is that anyting less would imply some limitations of what the compiler is allowed to do, and they did not want to have that when writing the standard. – hlovdal Feb 11 '11 at 12:30
5

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.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
4

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.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
4

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?

M.M
  • 138,810
  • 21
  • 208
  • 365
Ted
  • 61
  • 2
2

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.
Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
0

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

Chris
  • 515
  • 1
  • 6
  • 16
0

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

Damian K.
  • 172
  • 8