您当前的位置:首页 > 计算机 > 编程开发 > C语言

运算符的优先级总能起作用吗?

时间:12-30来源:作者:点击数:

有关运算符优先级的规则稍微有点复杂。在大多数情况下,这些规则确实是你所需要的,然而,有人也指出其中的一些规则本来是可以设计得更好的。

让我们快速地回顾一些有关内容:“运算符优先级”是这样一些规则的集合——这些规则规定了“运算符”(例如+,-,等等)的优先性,即哪一种运算符先参加运算。在数学中,表达式“2×3+4×5”和“(2×3)+(4×5)”是等价的,因为乘法运算在加法运算之前进行,也就是说乘法的优先级比加法高。

在c中,有16级以上的运算符优先级。尽管这么多的规则有时使c程序不易阅读,但也使C程序写起来容易多了。虽然这不是唯一的一种折衷方法,但这就是C所采用的方法。表16.1总结了运算符的优先级。

表16.1 运算符优先级总结(从高到低)
----------------------------------------------------------------------------------
  优先级            运算符
----------------------------------------------------------------------------------
  1                x[y](下标)
                   x(y)(函数调用)
                   x.y(访问成员)
                  x->y(访问成员指针)
                   x++(后缀自增)
                   x--(后缀自减)--
    2             ++x(自增)
                   --x(自减)
                  &x(取地址)
                   *x(指针引用)
                  +x(同x,和数学中相同)
                  -x(数学求负)
                  !x(逻辑非)
                  ~x(按位求反)
                   sizeof x和sizeof(x_t)(字节数大小)
   3               (x_t)y(强制类型转换)
   4              x*y(乘法)
                   x/y(除法)
                   x%y(求余)
   5              x+y(加法)
                   x-y(减法)
   6              x<<y(按位左移)
                   x>>y(按位右移)
    7              x<y,x>y,x<=y,x>=y(关系比较)
    8             x==y,x!=y(相等比较)
    9              x&y(按位与)
    10             x^y(按位异或)  .
    11             x | y(按位或)
    12            x&&y(逻辑与)
    13             x||y(逻辑或)
    14             x?y:z(条件)
                  x=y,x*=y,x/=y,x+=y,x-=y,<<=,>>=,&=,^=,|=(赋值,右结合性)
    16    x,y(逗号)

 

--------------------------------------------------------------------------------------

优先级最高的是后缀表达式,即运算符跟在一个表达式后面;其次是前缀或单目表达式,即运算符位于一个表达式的前面;再次是强制类型转换表达式。

注意:关于运算符优先级,最重要的是知道*p++和*(p++)是等价的。也就是说,在*p++中,++运算符作用在指针上,而不是作用在指针所指向的对象上。象“*p++=*q++;这样的代码在C中是随处可见的,其中的优先级和“(*(p++))=(*(q++))”中的是相同的。这个表达式的含义是“q+1,但仍用q原来的值找到q所指向的对象;p加1,但仍用p原来的值;把q所指向的对象赋给p所指向的对象”,整个表达式的值就是原来q所指向的对象。在C中你会经常看到这样的代码,并且你会有许多机会去写这样的代码。对于其它运算符,如果你记不住其优先级,可以查阅有关资料,但是,一个好的c程序员应该连想都不用想就能明白*p++的含义。

最初的C编译程序是为这样一种计算机编写的——它的某些指令对象*p++和*p++=*q++这样的代码的处理效率高得令人难以置信,因此,很多C代码就写成这种形式了。进一步地,因为象这样的C代码实在太多了,所以新机型的设计者会保证提供能非常高效地处理这些C代码的指令。

再下一级的优先级是乘法、除法和求余(也叫取模),再往后是加法和减法。与数学中的表达式相同,“2*3+4*5”和“(2*3)+(4*5)”是等价的。

再下一级是移位运算。

再往后两级分别是关系比较(例如x<y)和相等比较(x==y和x!=y)。

再往后三级分别是按位与、按位异或和按位或。

注意:关于运算符优先级,再次重要(即在知道*p++和x=y=z的含义之后)的是要知道x&y==z和(x&y)==z是不一样的。因为按位操作的运算符的优先级低于比较运算符,所以x&y==z和x&(y==z)是等价的。这两个表达式的含义都是“先看y和z是否相等(相等为1,不等为0),然后让比较结果和x进行按位与运算”,这与“先让x和y进行按位与运算,再比较其结果是否等于z”相差甚远。有人可能会争辩,按位与运算符的优先级应该高于比较运算符,但为时已晚,因为相应的标准是早在二十年前被定义的。如果你想把按位与的结果与别的东西进行比较,你就需要使用括号。

再往后两级是逻辑运算符,例如x&&y和x||y。注意,逻辑与(AND)运算符的优先级高于逻辑或(OR)运算符,这与人们讲话的方式是一致的。例如,请看下面的代码:   

    if(have_ticket&&have_reservation
    ||have_money && standby_ok){
    goto_airport();
    }

这段代码的含义可以这样来描述:“如果你有机票并且预定了航班,或者你有钱并且可以买到备用票,那么你就可以出发去机场了。”如果你用括号改变优先级,你就会得到一种截然不同的条件:

    /* not a recommended algorithm!*/
    if(have_ticket
    &&(have_reservation || have_money)
    &&standby_ok){
    goto airport ();
    }

这段代码的含义可以这样来描述:“如果你有机票,并且你预定好了航班或者有钱,并且可以买到备用票,那么你就可以出发去机场了。”

再下一级是条件表达式,例如x?y:z。这是一个if-then-else结构的表达式,而不是一条语句。条件表达式有时可以使程序简洁,有时也会造成语意的模糊。条件表达式具有右结合性,也就是说
    a?b:c?d:e
等价于 
    a?b:(c?d:e)

这一点与else—if结构很相似。

再下一级是赋值运算。所有的赋值运算符都具有相同的优先级。与C的其它双目运算符不同,赋值运算具有“右结合性”,即它是从右向左进行的,而不是从左向右进行的。x+y+z等价于(x+y)+z,x*y+z等价于(x*y)+z,而x=y=z等价于x=(y=z)。

注意:关于运算符优先级,次重要(即在知道*p++的含义之后)的是要知道x=y=z的含义。因为赋值运算具有右结合性,所以这个表达式等价于x=(y=z),其含义是“将z的值赋给y,然后再将该值赋给x”。象a=b=c=d=O;

这样的代码是很常见的,按从右向左的顺序,它把。赋给d,再赋给c,再赋给b,最后赋给a。

c中优先级最低的是逗号运算符。它连接两个表达式,先计算第一个表达式的值,扔掉后,再计算第二个表达式的值。只有当第一个表达式具有副作用时,例如赋值或函数调用,使用逗号运算符才有意义。逗号和赋值运算符经常在for循环语句中搭配使用:

    for(i=0,count=O;i<MAX;++i){
       if(interestmg(a[i])){
       ++count:
       }
    }

 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门