运算符优先级的问题
假如有下面的代码。你想在特定条件下让 high
变量的二进制形式左移四位然后加上`low``:
1 | if(flag & tmp){ |
或许你会为了代码可读性,将其更改成下面的格式:
1 | if(flag & tmp != 0) { |
很不幸的是,这两个 if
语句不能画上等号,因为你没有考虑到运算符优先级的问题,下面的语句实际上是:
1 | if(flag & (tmp != 0)) { |
运算符优先级规则
是不是与你预想的差之千里,为了更好的使用 C 语言,每个 C coder 都应该牢记下面的几点:
- 优先级最高的不是真正意义上的运算符。eg:数组下表、函数调用操作符、各结构成员选择操作符。它们都是自左向右结合的,这也就是为什么
a.b.c
的含义是(a.b).c
而不是a.(b.c)
。 - 单目运算符(概念不清楚就搜一下)的优先级仅次于前述运算符(
++
运算符--
运算符)。
上一条也说了:函数调用操作符是优先级最高的。假如p
是一个函数指针,我想通过这个指针来调用对应的函数,那么*p()
显而易见错了,因为它会被编译器理解成*(p())
,而我想要的效果是(*p)()
。
再举个关于前述运算符的例子。*p++
,它会被编译器理解成*(p++)
,而希望的效果是(*p)++
。 - 比单目运算符优先级低的就是双目运算符了。双目运算符中:算术运算符>移位运算符>关系运算符>逻辑运算符>赋值运算符>条件运算符(三目运算符)。
这一条中最重要的几个点就是:
- 任何一个逻辑运算符的优先级都要低于任何一个关系运算符。
- 移位运算符的优先级比算术运算符低,但是高于关系运算符。
- 6 个关系运算符的优先级不同。其中
==
和!=
优先级低于其他关系运算符的优先级。 - 逻辑运算符中。按位运算符优先级高于顺序运算符。每个“与”运算符优先级高于对应的“或”运算符。异或运算符介于按位与运算符和按位或运算符之间。
- 所有的赋值运算符优先级都是一样的(右 -> 左)。eg:
a = b = 0;
就是将a,b
赋值为 0。 - 逗号运算符的优先级最低。
例子是举不完,记住这几条结论,在敲代码的时候多留意运算符优先级的问题,用的多了自然就熟练了。
也有个偷巧的方法:疯狂加括号,你想让谁先运行就给谁加括号,但是这样不好,会让代码看起来臃肿,不推荐。