问题描述
我在C#和Java中发现了一些奇怪的东西。
让我们来看看这个C ++代码:
I found something a little strange in C# and Java.Let's look at this C++ code:
#include <iostream>
using namespace std;
class Simple
{
public:
static int f()
{
X = X + 10;
return 1;
}
static int X;
};
int Simple::X = 0;
int main() {
Simple::X += Simple::f();
printf("X = %d", Simple::X);
return 0;
}
在控制台中你会看到X = 11(。
In a console you will see X = 11 (Look at the result here - IdeOne C++).
现在让我们看一下C#上的相同代码:
Now let's look at the same code on C#:
class Program
{
static int x = 0;
static int f()
{
x = x + 10;
return 1;
}
public static void Main()
{
x += f();
System.Console.WriteLine(x);
}
}
在控制台中你会看到1(不是11! )(看看这里的结果 -
我知道你现在在想什么 - 这怎么可能?,但是让我们转到下面的代码。
In a console you will see 1 (not 11!) (look at the result here - IdeOne C#I know what you thinking now - "How that is possible?", but let's go to the following code.
Java代码:
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
static int X = 0;
static int f()
{
X = X + 10;
return 1;
}
public static void main (String[] args) throws java.lang.Exception
{
Formatter f = new Formatter();
f.format("X = %d", X += f());
System.out.println(f.toString());
}
}
结果与C#相同(X = 1,查看结果)。
Result the same as in C# (X = 1, look at the result here).
最后一次让我们来看看PHP代码:
And for the last time let's look at the PHP code:
<?php
class Simple
{
public static $X = 0;
public static function f()
{
self::$X = self::$X + 10;
return 1;
}
}
$simple = new Simple();
echo "X = " . $simple::$X += $simple::f();
?>
结果为11(查看结果)。
Result is 11 (look at the result here).
我有一点理论 - 这些语言(C#和Java)正在堆栈上制作静态变量X的本地副本(他们是否忽略静态关键字?)。这就是为什么这些语言的结果是1的原因。
I have a little theory - these languages (C# and Java) are making a local copy of static variable X on the stack (are they ignoring the static keyword?). And that is reason why result in those languages is 1.
这里有人,还有其他版本吗?
Is somebody here, who have other versions?
推荐答案
C ++标准规定:
§5.17[expr.ass]
§5.17 [expr.ass]
因此,如同在同一评价中你使用 X
和一个对 X
有副作用的函数,结果是未定义的,因为:
Hence, as in the same evaluation you use X
and a function with a side effect on X
, the result is undefined, because:
§1.9[intro.execution]
§1.9 [intro.execution]
在许多编译器上恰好是11,但不能保证C ++编译器不会像其他语言那样给你1。
It happens to be 11 on many compilers, but there is no guarantee that a C++ compiler won't give you 1 as for the other languages.
如果你仍然持怀疑态度,对标准的另一个分析得出相同的结论:标准也在上面的同一部分中说:
If you're still skeptical, another analysis of the standard leads to the same conclusion: THe standard also says in the same section as above:
在你的情况下 X = X + f()
除了 X
只评估一次。
由于评估顺序无法保证,在 X + f()
中,您不能理所当然地认为第一个f被评估然后 X
。
In you case X = X + f()
except that X
is evaluated only once.
As there is no guarantee on the order of evaluation, in X + f()
, you cannot take for granted that first f is evaluated and then X
.
我不是Java专家,但Java规则明确规定了评估顺序表达式,保证在。在 15.26.2部分。复合赋值运算符 Java规范还说 E1 op = E2
相当于 E1 =(T)((E1)op( E2))
。
I'm not a Java expert, but the Java rules clearly specify the order of evaluation in an expression, which is guaranteed to be from left to right in section 15.7 of Java Language Specifications. In section 15.26.2. Compound Assignment Operators the Java specs also say that E1 op= E2
is equivalent to E1 = (T) ((E1) op (E2))
.
在你的Java程序中,这意味着你的表达式再次等同于 X = X + f()
并且首先评估 X
,然后 f()
。因此,结果中不考虑 f()
的副作用。
In your Java program this means again that your expression is equivalent to X = X + f()
and first X
is evaluated, then f()
. So the side effect of f()
is not taken into account in the result.
所以你的Java编译器没有bug。它符合规格。
So your Java compiler doesn't have a bug. It just complies with the specifications.
这篇关于C ++和PHP与C#和Java - 结果不相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!