关于运算优先级的问题,我们可以先举个例子:
if(flags&FLAG)与if(flags&FLAG!=0)是不等价的,其不等价的原因就在于第二个语句没有考虑到运算符优先级。因为!=运算符的优先级是高于&的,所以第二个语句会被解释为:if(flag&(FLAG!=0)),显示与第一个语句是不等价。
此外在编程过程中,忽略了运算符优先级常出的一个错误有:假设hi和low是两个整数,它们的值介于0到15之间,如果r是一个8位整数,且r的低4位与low各位的数一致,而r的高4位与hi各位上的数一致。很自然会想到这样写:
r = hi<<4 + low;
但是很不幸,这样写是错误的。加法运算的优先级是要比移位运算的优先级高,因此以上的语言会被解释为:
r = hi << (4+low);
对于这种情况,一般有两种更正方法:第一种方法是加括号;第二种方法意识到问题出在程序员混淆了算术运算与逻辑运算,但这种方法牵涉到的移位与逻辑运算的相对优先级就更加不是那么明显。
r = (hi << 4) + low; r = hi <<4 | low;
加括号的方法虽然可以完全避免这类问题,但是表达式中有了太多括号反而不容易理解。因此,记住C语言运算符的优化级是有益的。
把这些运算符恰当分组,并且理解了各组运算符之间相对优先级,那么这张表还是可以记住的。
优先级最高者其实并不是真正意义上的运算符,包括:数组下标、函数调用操作符各结构成员选择操作符,它们都是自左于右结合。
单目运算符仅次于前述的运算符。在所有的真正意义上的运算符中,它们的优先级最高。函数调用的优先级要高于单目运算符的优先级。
优先级比单目运算符要低的,接下来是双目运算符。在双目运算符中,算术运算符的优先级最高,移位运算符次之,关系运行符再次之,接着是逻辑运算符,赋值运算符,最后是条件运算符。(条件运算符实际为三目运算符。)
我们需要记住的最重要的两点是:
此外,还要注意到6个关系运算符的优先级级并不相同,这一点或许让人感到有些吃惊。运算符==和!=的优先级要低于其他关系运算符的优先级。
任何两个逻辑运算符都具有不同的优先级。所有的按位运算符优先级要比顺序运算符的优先级高,每个“与”运算符要比相应“或”运算符优先级高,而按位异或运算符(^运算符)的优先级介于按位与运算符和按位或运算符之间。
在涉及到赋值运算符时,经常会引起优先级的混淆。考虑下面的这个例子,例子中循环循环语句的本意是复制一个文件到另一个文件:
while((c=getc(in)!=EOF) putc(c,out);
如果表达式再复杂一点,这类错误就很难被察觉。
未经允许不得转载:TacuLee » C的陷阱与缺陷之运算符优化级问题