C 优先级与结合性

Posted by 老沙
10月 31 2009

优先级:决定哪部分表达式先计算。
结合性:计算时是从左向右顺序,还是从右向左的顺序。

例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++)

Trackback URL for this entry