以下内容参考或引用
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);