Why does this expression produce different results in C# and C++?
Asked Answered
B

4

5

I have tried the following code in both C# and C++:

int a = 5;
int b = (a++)+(++a)+(a--)+(--a);

I noticed that the result of b is different in C# and C++. In C#, I got 23. In C++, I got 20.

Why is this so? Why would an identical expression produce different results in C# and C++? Is this because the two languages have different operator precedence rules?

Buntline answered 27/11, 2010 at 11:6 Comment(0)
M
6

C# evaluates this from left to right. In C++, funny expressions such as yours invoke undefined behavior, because you are changing a variable and reading it again without an intervening sequence point.

This means that different compilers (or even the same compiler with different optimization settings) are allowed to (and typically will) produce different results for (a++)+(++a)+(a--)+(--a).

Mashe answered 27/11, 2010 at 11:8 Comment(0)
P
4

The expression has well-defined behavior in C# (evaluation from left to right)

In C#, the output would be 24 (not 23)

int b = (a++)+(++a)+(a--)+(--a);

      // 5   +   7 + 7   +   5 = 24

In C++, the expression invokes Undefined Behaviour because a is modified more than once between two sequence points.

Protrusile answered 27/11, 2010 at 11:10 Comment(0)
C
0

Take a look here for the complete list for C++. As FredOverflow says, C# evaluates from left to right

Clive answered 27/11, 2010 at 11:10 Comment(0)
A
0

Needed to look this up anyway so figured I would post it here too.

From The C# 5.0 Spec

5.3.3.21 General rules for expressions with embedded expressions

The following rules apply to these kinds of expressions: parenthesized expressions (§7.6.3), element access expressions (§7.6.6), base access expressions with indexing (§7.6.8), increment and decrement expressions (§7.6.9, §7.7.5), cast expressions (§7.7.6), unary +, -, ~, * expressions, binary +, -, *, /, %, <<, >>, <, <=, >, >=, ==, !=, is, as, &, |, ^ expressions (§7.8, §7.9, §7.10, §7.11), compound assignment expressions (§7.17.2), checked and unchecked expressions (§7.6.12), plus array and delegate creation expressions (§7.6.10).

Each of these expressions has one or more sub-expressions that are unconditionally evaluated in a fixed order (emphasis mine). For example, the binary % operator evaluates the left hand side of the operator, then the right hand side. An indexing operation evaluates the indexed expression, and then evaluates each of the index expressions, in order from left to right.

The detailed rules for each kind of expression are in section 7. I won't list them all here, but the heuristic is left to right as written in code. E.g.

7.5.1.2 Run-time evaluation of argument lists

The expressions of an argument list are always evaluated in the order they are written. Thus, the example

class Test
{
     static void F(int x, int y = -1, int z = -2) {
          System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
     }
     static void Main() {
          int i = 0;
          F(i++, i++, i++);
          F(z: i++, x: i++);
     }
}

produces the output

x = 0, y = 1, z = 2
x = 4, y = -1, z = 3
Ascendant answered 18/5, 2017 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.