在C语言中有很多运算符,像求字节数运算符[sizeof],赋值运算符,算术运算符,关系运算符,逻辑运算符,条件运算符,位运算符,指针运算符等。这些运算符在运算时是有优先级的,会最终影响结果。所以了解其优先级以及运算方法是挺重要的(虽然本人觉得这些都可以通过加括号来解决,但是还是要了解一下,以便更快读懂他人程序)。
类型转换
在C语言中,有很多双目运算符(一个运算符有两个操作数),一般情况下两个操作数的数据类型要是一样的,不过当两边类型不一致时就要进行==类型转换==。而类型转换的最基本的原则是==往最高级转换==。其转换的关系如下图:
图中纵向代表转换的顺序,int->unsigned->long->double;而两个横向的转换是当表达式中出现了float会当作double来处理,出现了short,char类型都会当作int来处理,也就是说这步是必须的,必须执行的转换。所以我们得到以下的结论:
- 表达式的结果类型只有int/unsigned/long/double四种类型。
- 表达式的结果类型只要看表达式中数据类型最高的那个。
自增/自减
自增和自减概念类似,这里以自增为例。自增包括前自增和后自增。前自增(++i)是指变量先自增,然后将自增后的结果当作表达式的值;而后自增(i++)是指变量先将值当作表达式的值,然后再自增1。这个在大学学C语言就知道了,这里在提及是为了下面关于自增/自减的两种使用情况。
自增/自减操作符只能用于变量,不能用于表达式
1#include<stdio.h> 2 3int main(){ 4 int i=1; 5 printf("i = %d\n",i); 6 printf("i++ = %d\n",i++); 7 printf("i = %d\n",i); 8 printf("++i = %d\n",++i); 9 rintf("i = %d\n",i); 10 11 // error: lvalue required as increment operand 12 //printf("(-i)++ = %d\n",(-i)++); 13 //printf("++i++ = %d\n",++i++); 14 15 return 0; 16}
由注释的三行可知:当给表达式进行自增操作的时候,回报左值需要增量操作数。
在输出中,计算顺序是从右往左
1#include<stdio.h> 2 3int main(){ 4 int i=1; 5 // 输出多个自增 6 printf("i = %d\n",i); 7 printf("i = %d, i++ =%d\n",i,i++); 8 printf("i = %d\n",i); 9 printf("i++ = %d, ++i =%d\n",i,++i); 10 printf("i = %d\n",i); 11 12 return 0; 13}
根据下图输出的截图,我们发现运算的顺序是从右往左的。代码见 附件。
混合运算
虽然本人觉得这部分绝对是装x的作死的,因为多用()就能解决表达式的可读性,但为了读懂某些装x作死的coder写的code,还是稍微了解一下。
操作符的优先级
括号级别
这是C语言中运算级别最高的操作符了。单目运算符
第二级别的运算符有两个共同的特征:- 它们都是单目运算符(强制类型转换和长度运算符sizeof个人也觉得算单目)
- 它们都是从右往左运算的(右撇子三剑客之一)。
双目运算符
第三级别里面的操作符就“群魔乱舞”了。- 算术运算符
对于算术运算符,可能都知道乘除高于加减,但是还得记得取模%和乘除是同级的。 - 移位运算符
有点疑问,见问题&回答1。 - 关系运算符
记住一点,大于小于高于等于。 - 位操作符和逻辑操作符
位操作符和逻辑操作符算是双目运算符中比较特殊的两个操作符,其特殊之处如下:- 按位取反操作符和逻辑非操作符是单目运算符,跻身第二级别
- 按位操作符优先级高于逻辑操作符
- 按位与& > 按位异或^ > 按位或|; 逻辑与&& > 逻辑或||
- 算术运算符
三目运算符
这也是从右往左运算的操作符(右撇子三剑客之一)赋值家族运算符 这是除了不常用的逗号运算符以外优先基本最低的运算符了,而且也是最后一个从右往左运算的操作(右撇子三剑客之一)。
逗号运算符 这是优先级别最低的运算符,也是最不常用的运算符。
记忆要诀
上面的优先级还是比较繁琐的,还是下面的基础要诀比较重要:- 括号最重要,操作数越多优先级越低(单目>双目>三目)
- 双目中,算术运算符 > 移位运算符 > 关系运算符 > 位操作符 > 逻辑操作符
- 三目运算符(条件运算符) > 赋值家族运算符 > 逗号运算符
- 相同优先级中,按结合顺序计算。只有三种运算符是从右往左的,分别是单目运算符,条件运算符和赋值运算符。
剪刀法切割表达式
1short s; 2int i; 3float f; 4double d; 5unsigned u; 6printf("%d\n",123%s+(i+'@')+i*u-f/d);
剪刀法是将表达式中的符号按照优先级由低到高的顺序依次减开,而且除了右撇子三剑客之外都要从右往左开始剪。比如上式表达式中按下面的顺序剪开:
1. u-f
2. )+i
3. s+(
此时表达式将变成四个部分,分别是123%s[int],(i+’@')[int],i*u[unsigned],f/d[double]。最终的结果也是double类型的。
问题&回答
- Q:在移位运算符中,我们发现其用法是变量 » 表达式,按理说这样的用法4»1应该会报错的(和自增/自减类似),但是执行代码
printf("%d\n",4>>1);
会获得结果2。
A: 尚且无解