C操作符的优先级,结合性等

以下内容参考或引用

https://www.cnblogs.com/liushui-sky/p/7993122.html

 

操作符        描述                  用法实例                        结果类型        结合性         是否控制求值顺序

    ()            聚组                 (表达式)                       与表达式同         N/A                        N

    ()          函数调用            rexp(rexp,...rexp)              rexp             L-R                           N

    []            下标引用           rexp[rexp]                        lexp             L-R                        N

    .            访问结构成员      lexp.member_name        lexp             L-R                        N

   ->         访问结构指针成员 rexp->member_name     rexp           L-R                        N

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

++/--      前置/后置自增自减  lexp++/--lexp              rexp             R-L                        N

&             取址                       &lexp                          rexp               R-L                        N

*              间接访问                 *rexp                             lexp              R-L                        N

!               逻辑反                    *rexp                             rexp               R-L                        N

~            按位取反                  !rexp                             rexp                  R-L                      N

-             单目,表示负值        -rexp                            rexp               R-L                         N

+           单目,表示正值(实际无任何作用) +rexp         rexp               R-L                          N

sizeof      取其长度,已字节表示  sizeof(rexp)/sizeof(类型) rexp          R-L                          N

type        类型转换                   (type)rexp                     rexp            R-L                            N

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

*            乘法                         rexp*rexp                      rexp                l-R                            N

/           除法                          rexp/rexp                       rexp               L-R                           N

%         整数取余                   rexp%rexp                      rexp                L-R                          N

--------

+         加法                          rexp + rexp                    rexp               L-R                            N

-          减法                          rexp  - rexp                    rexp               L-R                            N

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

<<       左移位                      rexp <<rexp                   rexp              L-R                            N

>>       右移位                     rexp >> rexp                   rexp              L-R                            N

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

>         大于                         rexp  > rexp                     rexp              L-R                             N

>=    大于等于                     rexp  >= rexp                  rexp              L-R                             N

<         小于                         rexp  < rexp                     rexp              L-R                             N

<=   小于等于                      rexp  <= rexp                  rexp              L-R                             N

--------

==       等于                       rexp  == rexp                  rexp              L-R                             N

!=       不等于                     rexp  != rexp                  rexp              L-R                             N

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

&       位与                         rexp & rexp                  rexp              L-R                             N

--------

^        位异或                     rexp ^ rexp                  rexp              L-R                             N

--------

|         位或                         rexp | rexp                  rexp              L-R                             N

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

&&   逻辑与                      rexp && rexp            rexp               L-R                              Y

--------

||       逻辑或                      rexp || rexp                rexp               L-R                               Y

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

?:        条件操作符            rexp?rexp:rexp            rexp               N/A                              Y

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

=,+=,-=,*=,/=,%=,<<=,>>=,&=,&|,&^            rexp               R-L                                 N

,         逗号                       rexp,rexp                    rexp                L-R                                Y

 

说明:

同一优先级的运算符,运算次序由结合方向所决定。

简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。 而在一个运算量两侧的运算符优先级相同时, 则按运算符的结合性所规定的结合方向处理。 C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应先与“-”号结合, 执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。 最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。 C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。

 

 

在标准C语言的文档里,对操作符的结合性并没有作出非常清楚的解释。一个满分的回答是:它是仲裁者,在几个操作符具有相同的优先级时决定先执行哪一个。

每个操作符拥有某一级别的优先级,同时也拥有左结合性或右结合性。优先级决定一个不含括号的表达式中操作数之间的“紧密”程度。例如,在表达式a*b+c中,乘法运算的优先级高于加法运算符的优先级,所以先执行乘法a*b,而不是加法b+c。

但是,许多操作符的优先级都是相同的。这时,操作符的结合性就开始发挥作用了。在表达式中如果有几个优先级相同的操作符,结合性就起仲裁的作用,由它决定哪个操作符先执行。像下面这个表达式:

int a, b=1, c=2;       

a=b=c; 

我们发现,这个表达式只有赋值符,这样优先级就无法帮助我们决定哪个操作先执行,是先执行b=c

呢,还是先执行a=b?如果按前者,a的结果为2,如果按后者,a的结果为1。    

所有的赋值符(包括复合赋值)都具有右结合性,就是说在表达式中最右边的操作最先执行,然后从右到左依次执行。这样,先赋值给b,然后b再赋值给a,最终a的值是2。类似地,具有左结合性的操作符(如位操作符“&”和“|”)则是从左至右依次执行。所以,遇到一个表达式时,先根据运算符的优先级将表达式拆分成几个子表达式,然后在每个子表达式中根据运算符的结合性来进一步确定执行的顺序。

【特殊情况】

看下面这个C表达式:

a+++b; 

结果是(a++)+b还是a+(++b)呢?答案是前者,因为在遇到这种情况时,C编译器会将表达式按照从左往右的顺序尽量匹配出一个子表达式,所以当C编译器遇到a且后面有3个+号时,会首先尝试匹配a+++,当然这是没有意义的,所以接着尝试a++发现这是有意义的匹配,因此确定a++为第一个子表达式,然后再接着匹配+号和b。因此结果是(a++)+b。

这种情况不能算是上面所讨论的运算符优先级和结合性的特例,因为它发生在优先级和结合性判断之前,但确实具有一些迷惑性,所以建议在遇到这种情况时给其加上括号,以增加可读性且避免可能发生的不必要的错误。  

 

(自增自减运算符存在于C/C++/C#/Java等高级语言中,它的作用是在运算结束前(前置自增自减运算符)或后(后置自增自减运算符)将变量的值加(或减)一。

相较于这些语言中的+=和-=运算符,自增运算符更加简洁,且可以控制效果作用于运算之前还是之后,具有很大的便利性。)

用例1:

  int i=3;

int j=4;
  i++;
  ++j;
  printf("%d, %d\n", i, j);

对此,结果就是 4,5;下面我们来做一点小改动:

  int i=3;
  int j=4;
  int a = i++;
  int b = ++j;
  printf("%d, %d\n", a, b);
  
  结果又是多少呢?这里就开始体现出++前置与后置的区别了,结果是3,5。结合此例,我们回头再来理解一下“++前置:i自增1后再参与其它运算;++后置:i参与运算后,i的值再自增1”。很明显,a = i++;由于是先执行赋值运算,再自增,所以结果是a=3,i=4;而b = ++j;则因先自增,然后再赋值,所以b,j均为5。

 

用例2:

int a=1,b=5;
int c=a+++b;
printf("a:%d,b:%d,c:%d",a,b,c);

用例3:

int a=1,b=5;
int c=(a++)+(b++);// int c=a+++b++
printf("a:%d,b:%d,c:%d",a,b,c);

用例4:

int a=1,b=5;
int c=(a++)+(++b);
printf("a:%d,b:%d,c:%d",a,b,c);

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值