C++ and PHP vs C# and Java - unequal results

后端 未结 4 1861
天涯浪人
天涯浪人 2021-01-01 09:41

I found something a little strange in C# and Java. Let\'s look at this C++ code:

#include 
using namespace std;

class Simple
{
public:
    s         


        
4条回答
  •  失恋的感觉
    2021-01-01 10:45

    As Christophe has already written, this is basically an undefined operation.

    So why does C++ and PHP does it one way, and C# and Java the other way?

    In this case (which may be different for different compilers and platforms), the order of evaluation of arguments in C++ is inverted compared to C# - C# evaluates arguments in order of writing, while the C++ sample does it the other way around. This boils down to the default calling conventions both use, but again - for C++, this is an undefined operation, so it may differ based on other conditions.

    To illustrate, this C# code:

    class Program
    {
        static int x = 0;
    
        static int f()
        {
            x = x + 10;
            return 1;
        }
    
        public static void Main()
        {
            x = f() + x;
            System.Console.WriteLine(x);
        }
    }
    

    Will produce 11 on output, rather than 1.

    That's simply because C# evaluates "in order", so in your example, it first reads x and then calls f(), while in mine, it first calls f() and then reads x.

    Now, this still might be unrealiable. IL (.NET's bytecode) has + as pretty much any other method, but optimizations by the JIT compiler might result in a different order of evaluation. On the other hand, since C# (and .NET) does define the order of evaluation / execution, so I guess a compliant compiler should always produce this result.

    In any case, that's a lovely unexpected outcome you've found, and a cautionary tale - side-effects in methods can be a problem even in imperative languages :)

    Oh, and of course - static means something different in C# vs. C++. I've seen that mistake made by C++ers coming to C# before.

    EDIT:

    Let me just expand a bit on the "different languages" issue. You've automatically assumed, that C++'s result is the correct one, because when you're doing the calculation manually, you're doing the evaluation in a certain order - and you've determined this order to comply with the results from C++. However, neither C++ nor C# do analysis on the expression - it's simply a bunch of operations over some values.

    C++ does store x in a register, just like C#. It's just that C# stores it before evaluating the method call, while C++ does it after. If you change the C++ code to do x = f() + x instead, just like I've done in C#, I expect you'll get the 1 on output.

    The most important part is that C++ (and C) simply didn't specify an explicit order of operations, probably because it wanted to exploit architectures and platforms that do either one of those orders. Since C# and Java were developed in a time when this doesn't really matter anymore, and since they could learn from all those failures of C/C++, they specified an explicit order of evaluation.

提交回复
热议问题