运算符优先级
在对一些比较复杂的表达式进行运算时,要明确表达式中所有运算符参与运算的先后顺序,这种顺序称作运算符的优先级。表1列出了C语言中运算符的优先级,数字越小优先级越高。
表1 运算符优先级
优先级 | 运算符 | 说明 | 结合性 |
---|---|---|---|
1 | + + -- | 后置自增/自减 | 自左向右 |
1 | ( ) | 括号 | 自左向右 |
1 | [ ] | 数组下标 | 自左向右 |
1 | . | 结构体/联合体成员对象访问 | 自左向右 |
1 | -> | 结构体/联合体成员对象指针访问 | 自左向右 |
2 | + + -- | 前置自增/自减 | 自右向左 |
2 | + - | 加法/减法 | 自右向左 |
2 | ! ~ | 逻辑非/按位取反 | 自右向左 |
2 | (type) | 强制类型转换 | 自右向左 |
2 | * | 间接取指针指向的值(解引用) | 自右向左 |
2 | & | 取地址 | 自右向左 |
2 | sizeof | 计算大小 | 自右向左 |
3 | * / % | 乘/除/取余 | 自左向右 |
4 | + - | 加号/减号 | 自左向右 |
5 | << >> | 位左移/位右移 | 自左向右 |
6 | < <= | 小于/小于等于 | 自左向右 |
6 | > >= | 大于/大于等于 | 自左向右 |
7 | == != | 等于/不等于 | 自左向右 |
8 | & | 按位与 | 自左向右 |
9 | ^ | 按位异或 | 自左向右 |
10 | | | 按位或 | 自左向右 |
11 | && | 逻辑与 | 自左向右 |
12 | || | 逻辑或 | 自左向右 |
13 | ? : | 三元运算符 | 自右向左 |
14 | = | 赋值 | 自右向左 |
14 | += -= | 相加后赋值/相减后赋值 | 自右向左 |
14 | *= /= %= | 相乘后赋值/相除后赋值 | 自右向左 |
14 | <<= >>= | 位左移后赋值/位右移后赋值 | 自右向左 |
14 | &= ^= |= | 位与运算后赋值/位异或后赋值/位或运算后赋值 | 自右向左 |
15 | , | 逗号 | 自左向右 |
根据表1所示的运算符优先级,分析下面代码的运行结果。
int a =2;
int b = a + 3*a;
printf ("%d",b);
以上代码的运行结果为8,这是由于运算符“”的优先级高于运算符“+”,因此先运算3a,得到的结果是6,再将6与a相加,得到最后的结果8。
int a =2;
int b = (a+3) * a;
printf ("%d",b);
以上代码的运行结果为10,这是由于运算符“()”的优先级最高,因此先运算括号内的a+3,得到的结果是5,再将5与a相乘,得到最后的结果10。
其实没有必要去刻意记忆运算符的优先级。编写程序时,尽量使用括号“()”来实现想要的运算顺序,以免产生歧义。
多学一招:运算符优先级口诀
虽然运算符优先级的规则较多,但也有口诀来帮助记忆,完整口诀是“单算移关与,异或逻条赋”,具体解释如下所示:
(1)“单”表示单目运算符:逻辑非(!)、按位取反(~)、自增(++)、自减(--)、取地址(&)、取值();
(2)“算”表示算术运算符:乘、除、求余(,/,%)级别高于加减(+,-);
(3)“移”表示按位左移(<<)和位右移(>>);
(4)“关”表示关系运算符:大小关系(>,>=,<,<=)级别高于相等不相等关系(==,!=);
(5)“与”表示按位与(&);
(6)“异”表示按位异或(^);
(7)“或”表示按位或(|);
(8)“逻”表示逻辑运算符,逻辑与(&&)级别高于逻辑或(||);
(9)“条”表示条件运算符(? :);
(10)“赋”表示赋值运算符(=,+=,-=,=,/=,%=,>>=,<<=,&=,^=,|=,!=);