一个运算符优先级问题引发的血案

来源:互联网 发布:数据库安全性实验报告 编辑:程序博客网 时间:2024/05/17 03:55

近期写程序的时候,遇到了一个问题,前后困扰了我一周左右(实在惭愧),

没想到居然在最简单的点上栽跟头了,觉得有必要总结一下。


在往下看之前,还请大家看下如下的表达式:

 if( j & h_mask == 0)

(背景:h_mask = 1,  j为一个循环变量,比如 1 到 100)

从大家对代码逻辑的一般理解上,上面的表达式正确么? 


如果你已经发现了问题,后面不需要继续读下去。

如果你没有,看来你有必要进行复习下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 我都犯过 (很惭愧)。。





原创粉丝点击