Mittwoch, 2. Mai 2012

Undefined Behaviour in C# and C++

It occures that in C# and C++ the same code produces different behaviour:
 
//C#
 static void Main(string[] args)
        {
            var i = 5;
            for (int j = 0; j < 5; j++)
            {
                i = i++;
            }
            Console.Write(i); //Output: 5
            Console.ReadKey();
        }
 
 
//C++
#include 

int main()
{
 int i = 5;
 for(int j = 0; j < 5; j++)
 {
  i = i++;
 }
 std::cout << i; //Output: 10
 std::cin.get(); 

}


What is happening here? The Code-Snippet

int i = 5; 
i = i++;

provocates different behaviour in C# and C++. C# doesnt change the value of i (it remains at 5), but in C++ the variable i increments. The reason behind this is, that side effect Operators (as ++-Operator) may cause unexpected results if they are used on the same variable more then once in a single expression. The final expression
 
i = i++;
contains two Sub-Expressions:
 
//Nr.1: 
i = i;
//Nr.2: 
i++;
The order in which this two subexpressions will be evaluated in the whole expression is NOT DEFINED. In result two things can happen: 
Variant 1: Subexpression Nr.1 is evaluated first and then Subexpression Nr.2: This leads to follow: the value of i (5) is retrieved and gets assigned to i, so it gets the value of itsself (same as the return-type of the post-increment). i is still 5. But after that, Nr. 2. Subexpression evaluates. So i gets incremented. i is 6 now. (result as in c++) 

Variant 2: Subexpression Nr. 2 is evaluated first and then Subexpression Nr.1: the value of i (5) is retrieved and gets incremented. i is 6 now. But then the retrieved value of i (which is 5) is given back to i. i remains 5. The value didn't change. (result as in C#) it is not defined, if Variant 1 or 2 evaluate first, so it depends on the compiler and machine you use, which one of these will happen first. In fact it is not possible to say if i will stay 5 or change to 6.