编程语言 - 为什么算术表达式未针对 C# 中的乘以 0 进行优化

本文关键字:优化 为什么 表达式 编程语言 | 更新日期: 2023-09-27 17:56:56

为了计算乘法,您必须计算第一项,然后是第二项,最后是乘以两个值。

假设每个数字乘以 0 都是 0,如果第一项的计算返回 0,我希望整个乘法的计算结果为 0,而不计算第二项。

但是,如果您尝试此代码:

var x = 0 * ComplexOperation();

尽管我们知道 x 为 0,但仍调用函数 ComplexOperation。

优化的行为也与布尔运算符"&&"一致,该运算符仅在第一个项被评估为真时才计算第二个项。("&"运算符在任何情况下都会计算这两个术语)

我在C#中测试了这种行为,但我想几乎所有语言都是一样的。

编程语言 - 为什么算术表达式未针对 C# 中的乘以 0 进行优化

首先,对于浮点数,您的断言甚至不正确! 考虑0 * inf不是 0,0 * nan也不是 0。

但更一般地说,如果你在谈论优化,那么我想编译器可以自由地不评估ComplexOperation如果它可以证明没有副作用。

但是,我认为您实际上是在谈论短路语义(即语言功能,而不是编译器功能)。 如果是这样,那么真正的理由是 C# 正在复制早期语言(最初是 C)的语义以保持一致性。

C# 不起作用,因此函数可能会产生副作用。例如,您可以从内部打印内容ComlpexOperation或更改全局静态变量。因此,是否调用它由*合约定义。

您发现自己是与&&&签订不同合同的示例。

该语言定义了哪些运算符具有短路语义,哪些运算符没有。您的ComplexOperation函数可能会产生副作用,这些副作用可能是故意的,并且编译器不能自由地假设它们不应该仅仅因为函数的结果实际上未被使用而发生。

我还要补充一点,这将是混淆的语言设计。 会有大量的SO问题,大意是...

//why is foo only called 9 times?????????
for(int i = 0; i < 10; i++) {
    print((i-5)*foo());
}

为什么允许短路布尔值而不是短路0*? 好吧,首先我要说的是,将短路布尔值与副作用混合是代码中错误的常见来源 - 如果在将其理解为明显模式的维护者中使用得当,那么它可能没问题,但我很难想象程序员会完全习惯于整数中的漏洞 0。