为什么在运行此 C# 代码时会出现除以零异常?对于任何其他值,它返回 3*x。
int x = -2;
x += x++ + ++x % x-- + --x;
你得到那个例外是因为你评估0 % 0
. 表达式计算如下:
x++
计算结果为 -2,x 为 -1。
++x % x--
评估0 % 0
将引发异常的哪个(计算需要除以的余数,并且不能除以零)。
要查看结果为何3*x
适用于有效值,请考虑此表,其中x
最初具有值A
:
x | 表达 | 价值 | x 之后 =======+==============================+============ ==========+========= 一个 | x++ | 一个 | 一个 + 1 -------+----------------+------------- ----------+--------- A + 1 | ++x % x-- | (A + 2) % (A + 2) = 0 | 一个 + 1 -------+----------------+------------- ----------+--------- A + 1 | --x | 一个 | 一个 -------+----------------+------------- ----------+--------- 一个 | x++ + ++x % x-- + --x | A + 0 + A = 2*A | 一个 -------+----------------+------------- ----------+--------- 一个 | x += x++ + ++x % x-- + --x | A + 2*A = 3*A | 3*A -------+----------------+------------- ----------+---------
在第二行中,您可以看到分母是0
何时A = -2
导致异常。
鉴于 C# 用于评估表达式的规则,您可以像这样重写代码:
int x = -2;
int a = x++;
int b = ++x;
int c = x--;
int d = --x;
x += a + b % c + d;
在这里, 和 的b
值c
是0
。并且因为%
具有比 更高的优先级+
,所以首先评估该操作。所以,这就变成了:
x+= a + (0 % 0) + d;
这就是为什么你得到例外。
你的方程式:
x += x++ + ++x % x-- + --x;
不等于:
x += ((x++) + (++x))
%
((x--) + (--x));
由于%
具有比您的等式更高的优先级,例如:+
x += x++ + (++x % x--) + --x;
现在评估右手边:
x++ + (++x % x--) + --x;
//^^^
//First evaluation x returns -2 but gets modified to -1;
由于一元运算符 (++, --) 具有更高的优先级,它将评估第一个x++
返回的位置,-2
但将修改为-1
下次使用时可用的位置。
现在是第二部分:
(++x % x--)
//^^^
//X returns 0 and modifies to 0
第一部分具有++x
which return 修改x
(以前持有-1
)到0
并返回0
,下一部分是x--
,它修改x
为-1
但返回0
,因为它是一个后减量运算符。
所以你最终得到
0 % 0
因此例外。
你的方程相当于:
x = 2*x + ((2*x+2) % (x+2));
对于x >= 0
,这等于3*x
。对于x < 0
,它没有。
对于x = -2
,其中的一部分尝试被求值:-2 % 0
,它抛出 a DivideByZeroException
(这提到rem
对应于模运算符的 MSIL 指令%
可以抛出这个异常)。这样做是因为模 0 是未定义的,就像除以零一样。定义模的一种方法是除法后的余数。由于除以零后无法计算余数,因为除以零是未定义的,所以模 0 也是未定义的。