c语言的“逻辑短路”与 运算符优先级,有点矛盾?
c规定:&& 的优先权要高于 ||
c优化:在“exp1 && exp2” 中如果exp1为false,则不再计算exp2的值
c优化:在“exp1 || exp2” 中如果exp1为true,则不再计算exp2的值
那么:
int a=1;
int b=1;
int c=1;
int d;
d=a>0 || ++b>1 && c++>1
按照规定, 要先计算 && ,也就是需要计算出 ++b和c++
按照优化, 只要计算出 a>0 就可以了,不需要计算出 ++b和c++
我看《C 语言解惑》里面讲:应该按照优化计算,
x=1,y=1,z=1;
++x || ++y && ++z 只要计算++x即可以
如此说来 (exp1 || exp2 && exp3)和(exp2 && exp3 ||exp1)会有不同的结果,这也不符合生活习惯呀。这难道是“++副作用”
到底应该如何?
[解决办法]
////如此说来 (exp1 ¦ ¦ exp2 && exp3)和(exp2 && exp3 ¦ ¦exp1)会有不同的结果,这也不符合生活习惯呀。这难道是“++副作用” //===================================//你举的两个运算的含义分别如下://1)//(exp1 ¦¦ exp2 && exp3) //==> //(exp1 ¦¦ (exp2 && exp3))//==>//exp1 ? 1 : (exp2 && exp3)////2)//(exp2 && exp3 ¦ ¦exp1)//==>//((exp2 && exp3) ¦ ¦exp1)//==>//(exp2 && exp3) ? 1 : exp1////由此可以看出,这是不同的运算过程,当然很有可能产生不同结果////至于你说到的矛盾,并不存在,原因如下://&& 的优先权高于 || ,指的是数学中的结合律//比如: 2 * 3 + 4 * 5 = (2 * 3) + (4 * 5) = 6 + 20 = 26//但是因为计算机中的计算是一步步来的,所以计算过程可能是//2 * 3 + 4 * 5 = (2 * 3) + (4 * 5) = 6 + (4 * 5) = 6 + 20 = 26 //(方式1: 先计算运算符左边的表达式,这个比较符合我们的习惯)//但也有可能是//2 * 3 + 4 * 5 = (2 * 3) + (4 * 5) = (2 * 3) + 20 = 6 + 20 = 26 //(方式2: 先计算运算符右边的表达式)////但是我们的C语言中,具体采取的是哪种方式呢?//如果我没记错的话,很多运算的计算次序都没有规定死,是由编译器(比如VC++, tc是不同的编译器)的实现者自己选择的//即先算左边,还是先算右边,并不确定////然后让我们回到 _逻辑短路原则_ 这个话题//_逻辑短路原则_ 恰恰就是对 逻辑运算过程 计算次序的一个规定,规定:先计算运算符左边的表达式//那么,假设有一个运算//T && T || F && T//由运算优先级!,有//(T && T) || (F && T)//这时面临一个选择,先计算 || 左边还是右边?//参考 _逻辑短路原则_,先计算左边 (T && T) => T//从而有//T || (F && T)//再次参考 _逻辑短路原则_ //因为运算符是 || ,"或"运算,此时由左边的 T 即可确定整个运算式的值,//那么编译器判断计算可以结束,右边的(F && T)从而被掠过
[解决办法]
这个问题是偶的强项了,绝对没有冲突,只是绝大部分人对法典理解不够深刻。
运算符优先级不是运算优先级,而是结合性优先级,意指:高优先级的运算符所结合的变量或表达式,不能被低优先级的运算符分离。
前缀的++与后缀的++具有同样的优先级,只是执行结果不一样。他们的结合性优先级都高于&&,但是他们的运算优先级要低于||,表达式在取值时,按照递推结合,递归返回的顺序运算,所以编译器会先处理优先级低的运算符。
举个简单的例子:a+b*c,编译器会先处理+号,得知最终返回的是和值,然后再分析加号的左右两个操作数,或者操作表达式。
8知道有没有说明白,这个问题,额。。。。。。懂了就懂了,不懂就拉倒,应用开发的时候,完全可以忽略,毕竟,谁敢写楼主这样的表达式,是必定要被老大狠K的。
[解决办法]
3楼说法是不对滴,在C++里,短路早已经被纳入新标准,以加强移植性。