在我们编写程序的时候,一定要注意运算符的优先级问题,但这不是让我们去死记运算符优先顺序,这往往十分枯燥和乏味,而是在我们敲下代码前,仔细想想要敲的代码的运算符优先级,看是不是按照我们的想法进行运算的。
比如常量FLAG,FLAG是一个整数,且该整数倍的二进制表示中只有某一位是1,其他位是零。如果·对于整型变量flags,我们需要判断它在FALG为1的那一位上是否同样也为1。如果你想到这样写:
if (flags & FLAG != 0)
{
}
那么你就犯了一个错误,你忽略了优先级,其实因为!=的优先级高于&,因此,你写的代码其实是这样运算的:
if(flags & (FLAG!=0))
{
}
因此,这将会成为一个难以发现的bug,先判断了FLAG是不是为0,再将结果与flags 做&运算。只有在FLAG为1时,其结果才是正确的。
这样的例子还有很多,原书也列出了很多。
另外,原书提到我们需要记住的最重要的两点是:
1.任何一个逻辑运算符的优先级低于任何一个关系运算符。
2.移位运算符的优先级比算术运算符要低,但是比关系运算符高
记住了这两点,我们可以避免写出很多错误程序。
比如上面的错误就不会出现。
也能够避免下面的错误。
假设hi和low是两个整数,它们的的值介于0到15之间,如果r是一个8位整数,且r的低4位与low各位上的数一致,而r的高四位与hi各位上的数一致。很自然会想到这样写:
r = hi<< 4 + low
但是这样写还是错误的。它会先让4和low相加,然后再将hi做<<运算(左移)。可以加括号,也可以这样写:
r = hi << 4 | low
还有很重要的一点:注意涉及到赋值运算符时,经常会引起优先级的混乱。
比如
while (c=getc(in)!= EOF)
putc(c,out)
c似乎是赋予了get(in)的返回值,然后与EOF比较是否到达文件末尾以便决定是否终止循环。但是一定记住,赋值运算符的优先级低于任何一个运算符。因此c的值实际上是get(in)的返回值和EOF比较的结果。
今天的收获就是这些,希望我们在写程序的时候一定要注意运算符优先级,记住重要的那几点,如果能记住运算符优先级表当然更好。