为什么按位运算符不像逻辑"和\或"运算符那样智能

Ami*_*ich 5 c# optimization bit-manipulation operators

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

这是一个例子:

// 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();
Run Code Online (Sandbox Code Playgroud)

但是,按位运算符"| ="和"&="并不那么聪明:

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.
Run Code Online (Sandbox Code Playgroud)

我想知道他们为什么不以同样的逻辑方式工作.

D S*_*ley 10

一个澄清:

运营商&=|=上进行评估时,不按位运算符bool的S -它们是逻辑运算符,但它们的等价x = x & yx = x | y等不短路喜欢&&||这样做.

来自MSDN:

&运算符对积分操作数和bool操作数上的逻辑AND执行按位逻辑AND运算.

设计师可能已经实现了||=&&=,但由于它们将适合布尔类型的,没有太多的价值存在.


Eri*_*ert 8

D斯坦利的回答是正确的; 你的错误是在&应用时被认为是"按位"的bool.这是更好地认为&&&作为逻辑的急切和懒惰的版本,并且当应用于bool.

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

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

不好的理由是:表达式exprY可能会产生副作用,无论值是多少,您都希望始终发生这种副作用exprX.这是一个不好的理由,因为将表达式用于其副作用及其值是一个值得怀疑的做法.

好的理由是:它可以&比计算更快&&.

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

错误的错误. z = x && y 将生成为具有以下结构的代码:

if x goto CONSEQUENCE
z = false
goto DONE
CONSEQUENCE: z = y
DONE: 
Run Code Online (Sandbox Code Playgroud)

与简单地计算x & y和分配结果相比,这是很多指令z,大型代码需要更多时间来加载磁盘,更多时间进行jit编译,并在处理器缓存中占用更多空间.

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

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

现在,这并不是说你永远不应该&&用于布尔; 目前还没有程序在市场上取得的巨大成功归功于这种纳米优化的使用.我之所以指出它仅仅是因为根本不明确为什么在bool上应该有一个非短路的逻辑运算符.