2

Possible Duplicate:
Undefined, unspecified and implementation-defined behavior
Undefined Behavior and Sequence Points
Pre & post increment operator behavior in C, C++, Java, & C#

I have this code-snippet:

int x = 2;
int y = x + 4 * ++x;
// what is y???

And when I compile and test it in c/c++ I'll get:

// C/C++
y is 15

But via c# I'll get

// C#
y is 14

WHY?


A part of IL is:

locals init ([0] int32 x,
[1] int32 y)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.4
IL_0005: ldloc.0
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: dup
IL_0009: stloc.0
IL_000a: mul
IL_000b: add
IL_000c: stloc.1
IL_000d: ldloca.s y
Community
  • 1
  • 1
amiry jd
  • 27,021
  • 30
  • 116
  • 215

2 Answers2

5
int y = x + 4 * ++x;

In C and C++, the order of evaluation of each operand is unspecified which means either x or 4*++x can be evaluated before the other. Since the order of evaluation of the operands is unspecified, the result of the entire expression is unspecified.

If x is evaluated before 4*++x, then y will be computed as:

int y = x + 4 * ++x; //original

int y = 2 + 4 * ++x  //evaluate x first
      = 2 + (4 * 3)  //evaluate 4 *++x then
      = 14;

Similarly, if 4*++x is evaluated before x, then

int y = x + 4 * ++x; //original

int y = x + (4*3)  //evaluate 4 * ++x first
      = 3 + 12   //evaluate x then  (x is incremented)
      = 15;

In C#, the operands are required to be evaluated left to right, so you always get the first behaviour giving 14 as a result.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 2
    isn't it undefined behavior, because you're reading and modifying `x` in the same expression, with no sequence points separating the two? – jalf Oct 23 '11 at 10:53
  • Not just unspecified, UB in this case because of what @jalf mentioned – Praetorian Oct 23 '11 at 10:55
  • @jalf: Doesn't modifying an object more than once without any intervening sequence point invoke UB? – Nawaz Oct 23 '11 at 11:01
  • @Nawaz: modifying multiple times, or modifying as well as reading. As soon as you modify it, you can do *nothing else* with it in that expression – jalf Oct 23 '11 at 11:22
  • I can't understand why you got 3 up-vote!!!!! Your answer is so simple and hasn't any relationship with the Question! – amiry jd Oct 23 '11 at 11:55
  • @Javad_Amiry how come it has no relationship with the question? It explains the result you get in C++. It also explained the C# behaviour on a previous version, but it was edited out :( – R. Martinho Fernandes Oct 23 '11 at 11:57
  • Yes I see your update just now. But what about *standards*? Isn't c# against the normal and standard operands? Same as `c/c++`? I think this can cause some logic-errors for bilingual programmers. Isn't it? (My English-writing- is so bad ): so excuse me if my sentences grammar is not correct) – amiry jd Oct 23 '11 at 12:06
  • 2
    @Javad C# follows the C# standard and C++ follows the C++ standard. The two are different. This only causes problems for programmers that don't know both languages, and therefore should not be programming in both languages. In any case, it is ugly code that should be avoided. – R. Martinho Fernandes Oct 23 '11 at 12:26
  • I'm agree with you *`C# follows the C# standard and C++ follows the C++ standard. The two are different.`*. But I don't know how can I ask my Question. However there is a *`c-family`* languages, hmmm H don't know how to ask ): – amiry jd Oct 23 '11 at 12:35
  • @Javad: the "C family" of languages is a highly misleading term used to refer to various languages that share similar syntax, but are completely different from each other. Don't let yourself get confused by it. Treat C, C++, and C# as completely different languages, because that's what they are. They just look similar in syntax. – R. Martinho Fernandes Oct 23 '11 at 13:56
2

Actually, in C++ you just get undefined behavior, since the evaluation order of expressions is not always specified, so it's unclear whether the first use of x reads the old or new value. Both are possible, and in fact anything at all is possible because the standard explicitly says that it is undefined what happens.

C#, as a safe language, cannot allow such a situation and thus more strictly defines order of evaluation.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • 1
    The order of evaluation is *unspecified*. If it was *undefined* you could not write any useful C++ program. – R. Martinho Fernandes Oct 23 '11 at 10:56
  • Fixed this detail. The main issue, though, is that unsequenced reads and writes to the same variable are undefined behavior; the unspecified order of evaluation is just the cause of this. – Sebastian Redl Oct 23 '11 at 10:59
  • @R.MartinhoFernandes: The order of evaluation is unspecified, but the code shown here is still undefined. :) – jalf Oct 23 '11 at 11:23