为什么't位运算符不如逻辑& &;和& &;操作符

本文关键字:操作符 运算符 为什么 | 更新日期: 2023-09-27 18:03:02

我刚刚注意到,按位操作不像逻辑"和'或"操作那样"智能",我想知道为什么?

下面是一个例子:

// For the record
private bool getTrue(){return true;}
private bool getFalse(){return false;}
// Since a is true it wont enter getFalse.
bool a = getTrue() || getFalse(); 
// Since a is false it wont enter getTrue.
bool b = getFalse() && getTrue(); 
// Since b is false it wont enter getTrue.
b = b && getTrue();

然而,按位运算符"|="answers"&="就不那么聪明了:

bool a = getTrue();
a |= getFalse(); // a has no chance to get false but it still enters the function.
a = getFalse();
a &= getTrue(); // a has no chance to get true but still performs this operation.

我想知道为什么它们不能以相同的逻辑方式工作

为什么't位运算符不如逻辑& &;和& &;操作符

澄清一点:

运算符&=|=bool s上求值时不是位运算符,它们是逻辑运算符,但它们相当于x = x & yx = x | y,它们不像&&||那样短路。

从MSDN:

,operator对整型操作数执行位逻辑与操作,对bool型操作数执行位逻辑与操作。

设计者可以实现||=&&=,但是因为他们只有适合布尔类型,所以没有太多的价值。

D Stanley的答案是正确的;你的错误是认为&是"按位"时应用于bool。在应用于bool时,最好将&&&看作是逻辑与的急切版本和惰性版本。

现在有一个问题,你没有问,但实际上是更有趣的问题:

为什么首先有bool的AND和OR的非短路版本?也就是说,为什么你会说exprX & exprY而不是exprX && exprY呢?

不好的原因是:表达式exprY可能有一个副作用,无论exprX的值如何,您都希望它总是发生。这是一个不好的理由,因为使用表达式的副作用和它的值都是值得怀疑的做法。

好的理由是:计算&比计算&&要快。

这怎么可能?当然,如果我们可以在某些时候避免计算右边,那么我们就可以总是平均节省时间,对吧?

错错错。z = x && y将被生成为具有如下结构的代码:

if x goto CONSEQUENCE
z = false
goto DONE
CONSEQUENCE: z = y
DONE: 

与简单地计算x & y并将结果分配给z相比,这是很多指令,并且大代码需要更多的时间来加载磁盘,更多的时间来jit编译,并使用更多的处理器缓存空间。

此外,这些指令包含一个条件分支和一个非条件分支,显著增加了抖动必须处理的基本块的数量。("基本块"是一段具有明确开始和结束的代码,如果没有异常,基本块中的所有代码都将执行。)当需要分析的基本块数量太大时,抖动可能会选择避开某些优化。

最糟糕的是,任何条件分支都会给CPU一个机会让它的分支预测器做出错误的选择,这在某些情况下可能会产生严重的性能影响。

现在,这并不是说你不应该使用&&作为bool;目前还没有一个程序在市场上取得巨大成功是由于使用了这种纳米优化。我之所以指出这一点,仅仅是因为为什么在bool上应该有一个非短路逻辑运算符的原因并不完全明显。

主要区别在于您使用的是|/&还是||/&&。后者会短路(您称之为"智能"),而前者不会(这是处理布尔类型时操作符之间的唯一区别)。由于没有&&=||=操作符,您只注意到&=|=,正如符号所示,它们不会短路。

我认为&=|=可能存在,但&&=||=不存在,因为前者在数字类型中使用,短路没有意义。