操作符问题补充
- 表达式求值
- 整型提升
- 算数转换
- 操作符的属性
表达式求值
- 一般在操作符的时候,系统会根据不同的情况对一些表达式的求值方式有不同的影响,一般来讲,表达式的求值顺序一般可以根据操作符的优先级和结合型来决定,但往往还会产生不同的情况。
整型提升
先看这段代码:
char a , b , c;
scanf("%d %d ",&a,&b);
c = a + b;
- 可以思考一下,在三个char类型的字符相加,其过程应该是怎么样的?
这里我们需要了解一下整数提升的概念:
表达式的整型运算要在CPU(中央处理器)的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器长度。
- 因此,即使俩个char类型的字符相加,在CPU执行时实际上也要转换为CPU、内整形操作数的标准长度。
char a = '1';
//char类型的补码:00110001
//int类型的补码:00000000 00000000 00000000 00110001
char b = '2';
//char类型的补码:00110010
//int类型的补码:00000000 00000000 00000000 00110010
char c;
c = a + b;
printf("%d",c);
- 假设如果俩个char类型的a和b,他们的补码都是非常大的俩个数,那么他们相加肯定大于一个字节的长度,此时整型提升的作用就体现出来了,俩个char类型的字符提升成int类型,所加的值保留在char类型中需要采取的措施就是阶段,即只保留一个字节,其他字节删除。
这里需要提示一下,通用CPU是难以实现俩个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中每个小于int类型的整型值,都必须先转换为int或者unsigned int,然后才能送入CPU计算。
- 整型提升是按照变量的数据类型的符号为来提升的,整型提升有三种情况
- 负数的整型提升:高位补充符号位,即为1;
- 正数的整型提升:高位补充符号位,即为0;
- 无符号的整型提升:高位补充0.
- 关于char类型:
1.有符号的char类型的取值范围是-128~127
2.无符号的char类型的取值范围是0~255
算数转换
- 通过整数提升我们大概可以了解,在比小于int类型的字节长度在进行计算时CPU都会转化成int类型,那如果俩个大于int类型的数字,并且类型不匹配怎么办?这里就需要进行算数转换。
- 算数准换:如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。
long double
double
float
unsigned long int
long int
unsigned int
int
- 这些层次体系称为寻常算数准换,转换时从最下面的int向上转换。
操作符的属性
- 复杂表达式的求值有三个影响因素:
- 操作符的优先级
- 操作符的结合性
- 是否控制求值顺序
这里需要提示一下:在进行复杂的表达式求值的时候,首先确定优先级,相邻操作符按照优先级高低计算;当优先级相等时,结合性起作用;最后看是否控制求值顺序。
操作符 | 描述 | 结合性 | 是否控制求值顺序 | 优先级 |
---|---|---|---|---|
() | 聚组 | N/A | 否 | 1 |
() | 函数调用 | L-R | 否 | 2 |
[ ] | 下标引用 | L-R | 否 | 3 |
. | 访问结构指针成员 | L-R | 否 | 4 |
-> | 函数调用 | L-R | 否 | 5 |
()++ | 后缀自加 | L-R | 否 | 6 |
()-- – | 后缀自减 | L-R | 否 | 7 |
! | 逻辑取反 | R-L | 否 | 8 |
~ | 按位取反 | R-L | 否 | 9 |
+() | 正值 | R-L | 否 | 10 |
-() | 负值 | R-L | 否 | 11 |
++ () | 后缀自加 | R-L | 否 | 12 |
– --() | 前缀自减 | R-L | 否 | 13 |
*() | 间接访问 | R-L | 否 | 14 |
& | 取地址 | R-L | 否 | 15 |
sizeof | 求字节长度 | R-L | 否 | 16 |
(类型) | 类型转换 | R-L | 否 | 17 |
()*() | 乘法 | L-R | 否 | 18 |
/ | 除法 | L-R | 否 | 19 |
% | 取模 | L-R | 否 | 20 |
()+() | 加法 | L-R | 否 | 21 |
()–() | 减法 | L-R | 否 | 22 |
()<<() | 左移 | L-R | 否 | 23 |
()>>() | 右移 | L-R | 否 | 24 |
()>() | 大于 | L-R | 否 | 25 |
()>=() | 大于等于 | L-R | 否 | 26 |
()<() | 小于 | L-R | 否 | 27 |
()<=() | 小于等于 | L-R | 否 | 28 |
== | 等于 | L-R | 否 | 29 |
!= | 不相等 | L-R | 否 | 30 |
& | 按位与 | L-R | 否 | 31 |
^ | 按位异或 | L-R | 否 | 32 |
I | 按位或 | L-R | 否 | 33 |
&& | 逻辑与 | L-R | 是 | 34 |
II | 逻辑或 | L-R | 是 | 35 |
?: | 条件操作符 | N/A | 是 | 36 |
= | 赋值 | R-L | 否 | 37 |
+= | 以……加 | R-L | 否 | 38 |
–= | 以……减 | R-L | 否 | 39 |
*= | 以……乘 | R-L | 否 | 40 |
/= | 以……除 | R-L | 否 | 41 |
%= | 以……取模 | R-L | 否 | 42 |
<<= | 以……左移 | R-L | 否 | 43 |
()>>= | 以……右移 | R-L | 否 | 44 |
&= | 以……与 | R-L | 否 | 45 |
^= | 以……异或 | R-L | 否 | 46 |
I= | 以……或 | R-L | 否 | 47 |
, | 逗号 | L-R | 是 | 48 |