优先级:决定哪部分表达式先计算。
结合性:计算时是从左向右顺序,还是从右向左的顺序。
例1:
b=++a;
先看优先级:++ 优先级比 = 要高,先算++。
再看结合性:++ 的结合性是从右到左,这里就是它,直接算。
现在就剩下 = 号了,优先级就它一个了,但结合性还是 从右到左,那么现在把a 的值取出来赋值给 b 。
所以: 整个结果相当于
a = a + 1; b=a;
例2:
b=a++;
先看优先级,++ 虽然高,但是后置的(它的结合性是从左到右),这就意味着它返回左值。而返回值后就必须进行下面的计算
这里是 = ,运算全部完成后才能进行自身++运算,所以它最后算。我们这里先看 = ,再看结合性: 从右到左。故取 a 的值
赋值给 b ; 最后 a 的值加1 。
相当于: b=a; a = a + 1;
例3:
a+=b-=++c+4+e++;
这个够复杂吧,谁先? 单目运算符前缀 ++ 先算,然后是 + ,赋值运算最后。
然后看结合性。 -= += 都是从右到左,右边先算。故:
上例分解为:++c;b= b- e+c+4;a=a+b;e++
赋值运算符:结合性从右到左
先确定优先级,然后确定结合性。相同优先级的前提下,就要看结合性
结合性表示的是同级优先级,即同级运算符中的优先级。
优先级表示的是全局优先级,即不同运算符中的优先级。
对于自增自减表达式
前缀:先于表达式中其它部分的运算进行计算;
后缀:后于表达式中其它部分的运算进行计算。
++A ; 结合性,从右到左。 变量在右,返回右值。
//先看到 ++ 再看到 A ,返回 A 时 A 已经自增。
A++ ; 结合性,从左到右。 变量在左,返回左值。
//先看到 A,可以返回值,直接返回。A 本身再自增。
再来看看 B=A++; B=++A; 很容易就知道运算关系是怎么样的了,下面进行说明:
A++,执行后置运算,后计算A自增。先返回变量A的值参与表达式中其它部分的运算,整个表达式计算完成后,A才自增。
因其间返回的临时值参是一个常量,故该表达式不能写成:
A++ = 100;// 常量不能赋值
++A,执行前置运算,先计算A自增,然后返回A自增后的值。因为A自增操作已经完成,不必返回临时常量,直接返回A本身即可。
所以该表达式最终返回值是一个变量,故可以写成:
++A = 200; // 变量可以赋值
注意,理解它们, ++A, A++ ,要把它们当一个整体来看,即最小单位。在这里是没什么左右的,不要再分解它们。
自己总结的优先级
1. 括号操作符与关联和后置的自加自减(同级从左到右结合)
() isdigit('1')
[] array[4]
-> prt->age=34;
. *obj.age=34;
++ i++
— i–
2. 单字元的前置运算符(从右到左)
! if(!done)
~ flages=~flages;
++ ++i
— –i
+ int i=+1;
– int i=-1;
* int *p;
& p=&a;
sizeof sizeof(int);
3.数字运算符(乘除取模,高于加减 从左到右)
* i=2*4;
/ i=4/2;
% i=4%3;
+ i=2+4;
– i=4-2;
4.位移运算(从左到右)
>> int flages=flages<<2;
<<
5.比较大小(<,>高于==,!= 从左到右)
< if (i<2)
<=
>
>=
== if (i==2)
!=
6.位运算(&,^,|优先级从高到低,从左向右)
& flages=flages&42;
^
|
7.逻辑运算(从左到右)
&&
||
8.(右向左)
? : int i=(a>b)?a:b
9.赋值(从右向左)
=,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>=
10.
throw throw eclass("message");
11.逗号
, for (i=0,j=0;i<10;i++,j++)