假设high和low是两个整数,他们的值介于0-15之间,如果r是一个八位整数,且r的低四位与low的各位上一致,而r的高四位与high的各位上一致,很自然会想到要这样写:
r = high << 4 + low
但是很不幸,这样写是错误的,加法运算的优先级要比移位运算的优先级要高,因此本例实际上相当于:
r = high << (4 + low)
对于这种情况,有两种更正方式。第一种是加括号;第二种方法意识到问题出在程序员混淆了算术运算符与逻辑运算符的优先级。
r = (high << 4) + low //法1,加括号
r = high << 4 | low //法2,将原来的加号改为按位逻辑或
用括号的方法虽然可以完全避免这类问题,但是表达式中有了太多的括号反而不容易理解。因此记住C语言中的优先级是有益的。
优先级最高者其实并不是真正意义上的运算符,包括:数组下标,函数调用操作符,结构成员选择操作符。它们都是自左向右结合,因此a.b.c的含义是(a.b).c而不是a.(b.c)。
单目运算符的优先级仅次于上面说的运算符。在所有真正意义上的运算符中,他们的优先级最高。因为函数调用操作符的优先级要高于单目运算符,所以如果p是一个函数指针,要调用p所指向的函数,必须这样写:(*p)()。如果写成*p()
,编译器就会解析成*(p())
。类型转换也是单目运算符,它的优先级和其它单目运算符的优先级一样。单目运算符是自右向左结合,因此*p++
会被编译器解析成*(p++)
,即取指针p所指向的对象,然后将p递增1;而不是(*p)++,即取p指针所指的对象,然后将该对象递增1。
优先级比单目运算符低的,接下来就是双目运算符。在双目运算符中,算数运算符的优先级最高,移位运算符次之,关系运算符再次之,接着是逻辑运算符,条件运算符,最后是赋值运算符。
我们需要记住最重要的两点是:1)任何一个逻辑运算符的优先级低于任何一个关系运算符;2)移位运算符的优先级比算数运算符低,但是比关系运算符高。
六个关系运算符的优先级并不相同,这一点或许让人感到有些吃惊。==和!=的优先级要比其它关系运算符的优先级低。因此,如果我们要比较a与b的大小顺序是否和c于d的大小顺序一样,就可以这样写:a < b == c < d
。
任何两个逻辑运算符都具有不同的优先级。所有的按位运算符的优先级要比顺序运算符的优先级高。‘&’运算符要比’|’运算符的优先级高,而’^’运算符的优先级介于两者中间。