Bug 之 C++/C运算符

今天犯了一个低级错误, 写代码的时候太急 没有注意C++/C运算符的优先级关系, 结果导致条件判断无效,

示例代码:

    if( 0 & POLLIN_ALL == 0) //POLLIN_ALL是一个不为0的整数
    {
        printf("do here/n");
    }
   
这个代码编译后运行, 永远也无法printf("do here/n"), 原因是位运算符& 的优先级比关系运算符要低, 结果(POLLIN_ALL == 0)这个先被执行。


正确的做法:
    if( (0 & POLLIN_ALL) == 0)
    {
        printf("do here/n");
    }

[Summary]
 如果代码行中的运算符比较多,要用括号确定表达式的操作顺序,避免使用默认的优先级。
 运算符的优先级千万要小心, 不是想象的那么容易。
 

Appendix:

C++/C语言的运算符有数十个,运算符的优先级与结合律如表4-1所示。注意一元运算符 +  -  * 的优先级高于对应的二元运算符。

 

 

 

优先级

 

 

 

运算符

 

 

 

结合律

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

( )  [ ]  ->  .

 

 

 

从左至右

 

 

 

!  ~  ++  --  (类型) sizeof

 

+  -  *  &

 

 

 

 

 

从右至左

 

 

 

 

 

 

 

*  /  %

 

 

 

从左至右

 

 

 

+  -

 

 

 

从左至右

 

 

 

<<  >>

 

 

 

从左至右

 

 

 

<   <=   >  >=

 

 

 

从左至右

 

 

 

==  !=

 

 

 

从左至右

 

 

 

&

 

 

 

从左至右

 

 

 

^

 

 

 

从左至右

 

 

 

|

 

 

 

从左至右

 

 

 

&&

 

 

 

从左至右

 

 

 

||

 

 

 

从右至左

 

 

 

?:

 

 

 

从右至左

 

 

 

=  +=  -=  *=  /=  %=  &=  ^=

 

|=  <<=  >>=

 

 

 

 

 

从左至右

 

 

 

运算符的优先级与结合律

 

 

 

l         如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。

 

由于将表4-1熟记是比较困难的,为了防止产生歧义并提高可读性,应当用括号确定表达式的操作顺序。例如:

word = (high << 8) | low

if ((a | b) && (a & c))  

--  作者:原野
--  发布时间:2004-7-24 22:47:00

--  C语言运算符的优先级
算术运算符(*、 +、 - 、 %、 /)
                     关系运算符(<  <=  >  >= == !=)
                     逻辑运算符(! && ||)
              赋值运算符(=)
                        (+=、-=、*=、 /=、%=、)
              逗号运算符(,)
              条件运算符(?:)
              长度运算符(sizeof)
              位运算符(~ 、&、| ^)
优先级算术运算符 高于、位移位运算符 高于 关系运算符 高于 位逻辑运算符 高于 逻辑运算符 高于条件运算符 高于 位逻辑自反赋值运算符
   位自反赋值运算符优先级等同于算术自反赋值运算符等同于赋值运算符

C++中运算符优先级的学习注解

陈智罡chzg99@21cn.com
 

 

提起运算符的优先级,很多了解C++的过来人都会想:这有什么难的?不就是谁的优先级高就算谁么。确实如此,运算符的优先级不是一个大问题,但对于一个初学者来说,却经常容易在上面迷糊与犯错。而对于一个了解C++的人来说,我相信也会偶尔在上面摔倒,不信就继续往下读。

 

 

“优先级高的先运算”带来的困惑

 

 

 

C++中运算符的优先级有一张表,表里把运算符进行了分类,这张表是不需要死记硬背的,只要有个大致的轮廓就OK了。例如应该记住最低优先级是逗号运算符,其次是赋值运算符,再其次是三目运算符。而关系运算符的优先级高于逻辑运算符(不包括逻辑非运算),算术运算符的优先级高于关系运算符,象++﹣﹣的优先级比前面几个都高,但最高的要属()了。知道这些后,你的脑海里一定有一条准则了:优先级高的先运算。那么下面看一个例子:

 

int x=1,y=0;

 

!x&&x+y&&++y;

 

上面的语句中出现了!、&& 、+、++这四个运算符,那么问题来了,到底先算谁呢?

 

有一个姓蔡的同学站起来说,++运算符在这里面优先级最高,理所应当最先算++,既先计算++y,再算!x,再算x+y,最后把它们&&起来。按照蔡同学的思路,第二步的结果是0&&x+y&&1,由于&&是严格运算,有一个为0结果既为0,所以不需要计算x+y了,整个语句的结果是:假。按照上面蔡同学的说法,执行完后y的值应该是1了,这对不对呢?

 

一位姓高的同学站起来反驳道,我觉得应该先计算!x,如果值为假,则不需要计算下去,最后结果为假。如果值为真,再计算x+y,同理如果其值为真,再去计算++y,否则最后结果也为假。

 

蔡同学不服起来说,高同学你觉得++和!谁的优先级高呢?高同学答道,那当然是++高。蔡同学接着问,那为什么还要先计算!呢?高同学答不出来了。

 

是呀,为什么要先算!呢?

 

 

 

加括号确定优先级的方法

 

 

 

高同学说的是正确的,为什么呢?下面我给大家解释一下。当多个优先级不同的运算符在一起时,为了不混淆,可以先加上括号,这样就分出层次了,相同层次的考虑结合性问题,当确定下来先算那块时,再往这块里面深入。例如上面的例子,我们可以这样加上括号:从左向右看,由于!比&&优先级高,所以有(!x),又由于&&比+优先级低,所以有(x+y),而++优先级高于&&,所以(++y)。这样整个式子就变成了:(!x)&&(x+y)&&(++y),最外层的是两个&&运算,由于&&的结合性是从左至右,所以上式可看成:A&&B&&C,先计算A,再计算B,最后算C。由于x=1,则!x就为假,后面的就不需要再算了,整个语句的值为假。执行完后,y的值没变,还是0。

 

所以碰到不清楚先算谁后算谁时,先加个括号看看,就明白了先后次序。下面做一个加括号的练习:给语句c=a>b?a:b;加括号。此语句有三个运算符:=、>、? :,应该怎样加括号呢?

 

第一种方案:c=((a>b)?a:b);

 

第二种方案:c=(a>(b?a:b));

 

第三种方案:(c=a)>(b?a:b);

 

应该是那一种呢?按照运算符优先级的高低顺序,>优先级高于=,所以不可能把(c=a)括起来。而>优先级高于? :运算符。所以也不可能把(b?a:b)括起来。因此,第一种答案正确。

 

 

 

下面再看一个类似的例子:

 

int i=8,j=4,k;

 

k=i<j?++i:++j;

 

猛然一看,有些人上来可能就要计算++i和++j了。这里不妨先加括号看看。从左至右看,<的优先级高于=而且又高于? :,所以有k=(i<j)?++i:++j,再继续向右看,由于++高于? :,所以k=(i<j)?(++i):(++j),这样相当于k=A?B:C,先算A的值,若为真,则值为B,既算一下++i,若为假,则值为C,既算一下++j。整个语句执行完后,k的值为5,i的值为8,j的值为5。

 

所以运算符的优先级千万要小心,既不是想象的那么难,也不是想象的那么容易。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值