- 整型提升
- 表达式求值
- 隐式类型转换
- 数据类型及大小
- 截断&提升
- 代码示例1
- 代码示例2
- 代码示例3
- 代码示例4 -sizeof
- 算术转换
- 代码示例1
- 表达式属性
- 结语
要想知道什么是整型提升,那就要从表达式求值说起
表达式求值表 达 式 求 值 的 顺 序 一 部 分 是 由 *** 作 符 的 优 先 级 和 结 合 性 决 定
同 样,有 些 表 达 式 的 *** 作 数 在 求 值 的 过 程 中 可 能 需 要 转 换 为 其 他 类 型
什么是表达式? 举个最简单的例子
int main() { int a=3; int b=5; int c = a + b * 7; //c的式子即为表达式 return 0; }
而C的整个式子就是一个表达式求值
在这之中,参与计算的两个变量以及结果变量都是int类型,并不需要进行整型提升
在我们日常编写代码的时候,编译器经常会有隐式类型转换
隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的
为了获得这个精度,表达式中的字符和短整型 *** 作数在使用之前被转化为普通整型,这种转换称为整型提升
float f =3.14 int num =f;
在上面这个代码中就有隐式类型转换,由float型转换为int型
但是会有精度的丢失
此时num为3
我们知道,不同数据类型的数据大小如下
数据类型及大小可以看到,short类型和char类型的字节数都是小于int类型的
当我们将一个int类型的数据存放到char中时,会发生截断
截断&提升把四个字节放在1个字节的内容中,截断,只保留一个字节
把数字5放入char类型中,5的4个字节的内容会被截断
示例
char a = 3; //00000000000000000000000000000011 为3的二进制 //00000011 -a
在char类型a中,只存放了3的后8位(1个字节)的内容
这就是截断的表现形式
在char类型数据的表达式求值中,就会发生整型提升
规则如下:
代码示例1把最高位视为符号位进行提升,在a和b的8位码前加24个0
#includeint main() { char a = 3; //00000000000000000000000000000011 为3的二进制 //00000011 -a char b = 127; //00000000000000000000000001111111 为127的二进制 //01111111 -b char c = a + b; //把最高位视为符号位进行提升 //在a和b的8位码前加24个0 //00000000000000000000000000000011 //00000000000000000000000001111111 //00000000000000000000000010000010 //10000010 为char c //11111111111111111111111110000010 -补码 //11111111111111111111111110000001 -反码 //00000000000000000000000001111110 -原码 // -126 //发现a和b都是char类型的,都没有达到一个int的大小 //这里就会发生整型提升 printf("%dn", c);//%d是有符号数,打印原码 return 0; }
编译器中,负数是以补码的形式存放的
但在使用的时候,要先转换成原码再计算其数值
代码示例2再来看一个比较大小的示例
int main() { char a = 0xb6; short b = 0xb600; int c = 0xb6000000; if(a==0xb6) printf("a"); if(b==0xb600) printf("b"); if(c==0xb6000000) printf("c"); return 0; }
猜猜打印结果是什么?
是这个吗?
a b c
错!
运行后,我们会发现编译器只打印了c这个字符
因为if只会比较整型
而char和short类型都不足4个字节,在比较的时候需要进行整型提升
提升之后的结果与原数据不同
而int c本身就是整型,无须进行整型提升
int c = 0xb6000000;
所以代码只打印了字符c
代码示例3
再来看下面的这个代码,打印的结果是几呢?
#includeint main() { int a = 3; int b = 5; short s = 5; printf("%un", sizeof(s = a + 3)); return 0; }
结果为2
因为最后的s是短整型,推断出来的长度为2
代码示例4 -sizeof
int main() { char c=1; printf("%un",sizeof(c));//1 printf("%un",sizeof(+c));//4 printf("%un",sizeof(-c));//4 printf("%un",sizeof(!c));//4 return 0; }
当+c和-c参与计算的时候,就会进行整型提升
这里涉及到了另外一个重要的知识点,sizeof括号中表达式的问题
下篇博客会详细介绍!
算术转换
说完整型提升,接下来就是和隐式类型转换很像的算术转换
如果某个 *** 作符的各个 *** 作数属于不同的类型,那么除非其中一个 *** 作数转换为另外一个 *** 作数的类型,否则 *** 作就无法进行。
下面的层次体系称为寻常算术转换
具体是怎么转换的呢?
在进行运算的时候,如果某个 *** 作数的类型在上表中排名较低,那么首先要转换为另外一个 *** 作数的类型后,再执行运算。
简单地说,就是从下往上转换
注意:算术转换要合理,不然会有潜在的问题
代码示例1
下面的是一个简单算术转换的示例
在int型和float类型一起计算的时候
int类型会转换为float类型进行计算
#includeint main() { int a=3; float f =5.5; float ra =a+f; //算术转换,int-->float return 0; }
表达式属性
这里可以引出另外一个知识点,表达式的属性
表达式的两个属性:
- 值属性
- 类型属性
如以下代码中
-
a+b的结果30就是这个表达式的指属性
-
类型属性是int
int main() { int a =10; int b=20; a+b;//表达式2个属性:值属性,类型属性 //30 值属性 //int 类型属性 return 0; }
结语
本篇博客到这里就结束了
如果对你有帮助的话,还请点个赞再走吧!
这对我非常重要!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)