表达式求值
1.1 整型提升
内容的代码都是在VS2022上实现的
C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型
提升。
如果一个变量的类型是小于 int 类型 的 那么在进行相应操作的 时候 就会进行整型提升
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长
度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转
换为int或unsigned int,然后才能送入CPU去执行运算。
整形提升的实例讲解:
#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
int main()
{
char a = 5;
// 5是一个整数
// 00000000000000000000000000000101
// 但是char 类型只能存放一个字节 也就是8位二进制
// 那么此时的a 就是 00000101
char b = 125;
// 同理 这里的b 就是 01111101
char c = a + b;
// 此时的 a和b都是char类型 长度是小于int类型的长度的
// 在计算的时候默认就会 整形提升
// 如何整形提升呢
// 1. 有符号整数提升是按照变量的数据类型的符号来提升的
// 2. 无符号整数提升 ,高位补0
// 而这里的char 倒底是signed char 还是 unsigned cahr
// 这个是取决于编译器的 在vs上 就是signed char 也就是有符号char
// 这个时候 a和 b 都是补到32位 也就是前面一直+0
// 00000000000000000000000000000101 a
// 00000000000000000000000001111101 b
// 00000000000000000000000010000010
// 但是char只能存在一个字节 所以c 就是 10000010
printf("%d\n", c);// -126
// %d 按照有符号整数的形式进行打印
// 这里也发生的整形提升
// 此时的c 是有符号的 并且还有符号位 因此补32位
// 11111111111111111111111110000010 - 补码
// 此时要打印原码
// 10000000000000000000000001111101 - 反码
// 10000000000000000000000001111110 - + 1 成原码
// 而这个原码的值就是 -126 因此打印的值就是-126
return 0;
}
1.2算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
算数转换都是向大的类型转换的
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
警告:
但是算术转换要合理,要不然会有一些潜在的问题
float f = 3.14;
int num = f;//隐式转换,会有精度丢失
1.3 有关表达式的一些问题
我们先来看一个表达式:
a*b + c*d + e*f
这个是有问题的
因为无法确定唯一的计算路线
有两个解决方法: 1. 用括号 2.拆表达式
还有一个问题
c + --c;
这个表达式也是有问题的
左边的操作数c 是–前准备的还是-- 后准备的呢
我们再来看一个:
我们可以发现 这段代码在不同的编译器当中 输出的结果是不一样的
因此 这种代码是不推荐我们去编写的
还有一种表达式
我们在上述这个代码中 我们根本无法确定 fun()的值到底是什么时候确定的
我们只能知道是先算乘法再算加法 但是 fun()函数的返回值是先返回到那个呢
实际上这里的结果是-10 也就是 2 - 3 * 4 但是在分析时就会让人头疼 不推荐去编写
最后一个表达式
定的
我们只能知道是先算乘法再算加法 但是 fun()函数的返回值是先返回到那个呢
实际上这里的结果是-10 也就是 2 - 3 * 4 但是在分析时就会让人头疼 不推荐去编写
最后一个表达式
我们可以发现这段代码在不同的编译器输出的结果是不一样的