近期写程序的时候,遇到了一个问题,前后困扰了我一周左右(实在惭愧),
没想到居然在最简单的点上栽跟头了,觉得有必要总结一下。
在往下看之前,还请大家看下如下的表达式:
从大家对代码逻辑的一般理解上,上面的表达式正确么?
如果你已经发现了问题,后面不需要继续读下去。
如果你没有,看来你有必要进行复习下C语言的运算符优先级的知识点了。
从上面的表达式逻辑来看,是想先与掩码做位与&运算,然后判断是否为0。
粗略一看,没错啊,上面的语句是觉得有可能执行的,对吗?
为什么大家会那样认为? 因为大家潜意识认为 & 先于 == 执行 ,事实上呢?
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | 双目运算符 | ||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
& 与 &&的优先级都比 == 低 !!!
那么,由于 h_mask == 0 判断结果为0, 那么j & 0 一定为0,也就是说此if语句一定不会
执行,跟大家的预期不一样。
看到这里的童鞋,请务必引以为戒。
很多难debug的问题,都是因为犯了低级的错误,如:
1. 传递局部变量的指针并在被调用函数中修改此实参 (可能出现内存覆盖)
2. 运算符优先级问题
3. 指针的指针 ** 与 指针 * 概念不清晰导致用错
4. switch语句中该break的地方没用break,导致走到了其他case,
5. 申请了内存,不用的时候未记得释放
(在C++里面,要理清父子类的关系,用正确的instance去释放内存)
最后,对此类运算符问题总结下:
1. 最好在写程序时弄清表达式中运算符之间的优先级关系
2. 表达式之间“分段”,将相关的部分用()括起来。如:
if( j & h_mask == 0)
写成:
if( (j & h_mask) == 0)
可能很多人看了后,觉得自己不会犯这样的错误,可是写了一些程序后,会发现
自己或多或少犯了些低级错误,我个人不得不承认,2,3,4 我都犯过 (很惭愧)。。