当时我正在为我的计算机建筑课阅读我的课本,我偶然发现了这样的说法。
逻辑运算符'
&&‘和'||’与其位级对应的'&‘和'|’之间的第二个重要区别是,如果表达式的结果可以通过计算第一个参数来确定,则逻辑运算符不计算其第二个参数。因此,例如,表达式a && 5/a永远不会导致除法为零,表达式p && *p++永远不会导致空指针的取消引用。(计算机系统:程序员的观点,布莱恩特和奥哈拉龙,第三版,第57页)
我的问题是,为什么C中的逻辑运算符是这样的呢?使用作者的a && 5/a示例,C不需要计算整个表达式,因为&&要求这两个谓词都是真的吗?同样的问题也适用于他的第二个例子。
发布于 2016-09-21 10:28:03
短路是一种性能增强,碰巧对其他用途很有用.
您说“C不需要计算整个表达式吗?因为&&要求这两个谓词都是真的?”但想想看。如果&&的左手侧为false,那么右手侧的计算值是否重要?false && true或false && false,结果是相同的: false。
因此,当&&的左手侧被确定为false时,或者||的左手侧被确定为true时,右边的值并不重要,可以跳过。这使得代码更快,消除了评估潜在昂贵的第二次测试的需要。想象一下,如果右边调用了一个函数,该函数扫描了一个给定字符串的整个文件?如果第一个测试意味着你已经知道了综合答案,你不想跳过这个测试吗?
C决定不再保证短路,而是保证评估的顺序,因为这意味着你提供的安全测试是可能的。只要测试是幂等的,或者只有在没有短路时才会产生副作用,这个特性是可取的。
发布于 2016-09-21 10:17:50
一个典型的例子是空指针检查:
if(ptr != NULL && ptr->value) {
....
}如果不进行短路评估,则在取消引用空指针时会导致错误.
该程序首先检查左侧部分ptr != NULL。如果计算结果为false,则不需要计算第二部分,因为已经很清楚,结果将是false。
发布于 2016-09-21 10:20:35
在表达式X && Y中,如果X被求值为false,那么我们知道X && Y始终是false,不管Y的值如何。因此,没有必要对Y进行评估。
在您的示例中使用了这个技巧来避免0的除法。如果将a计算为false (即a == 0),则不计算5/a。
它也可以节省很多时间。例如,在计算f() && g()时,如果对g()的调用很昂贵,如果f()返回false,则不计算g()是一个很好的特性。
https://stackoverflow.com/questions/39613707
复制相似问题