本期介绍🍖
主要介绍:那些不被轻易发现的类型转换,隐式类型转换和显示类型转换👀。
文章目录
- 一、前言🍖
- 二、隐式类型转换🍖
- 2.1 整形提升🍖
- 2.1.1 例题1🍖
- 2.1.2 例题2🍖
- 2.1.3 例题3🍖
- 2.2 算数转换🍖
- 三、显式类型转换🍖
一、前言🍖
C语言是一种强类型语言,当使用一种类型代替另外一种类型进行操作时或者存在两个不同类型的对象进行操作时,首先就得进行类型的转换然后再说其他。而类型转换的方式一般可分为隐式类型转换(也称:自动类型转换)和显示类型转换(也称:强制类型转换),两者有着本质上的区别。
隐式类型转换是由编译器自动进行的,不需要人为的干预,而且我们也观察不到类型是如何进行转换的,所以被称为:“ 隐式 ”。而显式类型转换是由程序员明确指定的,所以才被称为:“ 强制类型转换 ”。
二、隐式类型转换🍖
有些表达式的操作数在求值的过程中可能需要转换为其他的类型,而这种你不知晓的类型上的转换通常分为两种情况:整形提升和运算转换。
在讲整形提升和算数转换之前,还得再补充一个知识点:截断操作。何为截断操作呢?下面举个例子:char a = 3;
。大家有没有想过字面常量3是如何存储到char变量a中去的呀?注意这里的字面常量3本质上是一个整数,而一个整数所占的内存空间是32个二进制位,所以这时的3在内存存放的补码如下图所示。但是你想啊,字符变量a只能存放1个字节(即:8个二进制位),怎么可能放得3呢。所以这个时候就要发生截断了,截断的规则:挑低位的字节数,放置到需要截断存储的变量中去,如下图所示。
2.1 整形提升🍖
C语言的整形算数运算总是至少以默认的整形类型(int型)的精度来进行,也就是说参与运算的操作数最小也不能小于4个字节的精度,如若精度小于4个字节该操作数就必须提升成整形的精度。所以为了获得这个精度,表达式中字符型(char)和短整型(short)操作数在使用之前就应该被转换为普通整形,这种转换被称为:整形提升。
那大家有没有想过为什么最小是以整形的精度来进行运算呢?其实表达式的整形运算是在CPU内的整形运算器(ALU)执行,而该运算器操作对象的字节长度一般就是int型的字节长度。因此CPU是无法实现直接对2个char类型的操作数的运算,而是通过先转换为CPU内整形操作数的标准长度然后再进行加法运算的。
整形提升前提条件:只有当表达式中出现长度可能小于int型的整形值时,才须要对该值进行整形提升转换为int或unsigned int型,然后再送入CPU去执行运算。
整形提升的规则:对于有符号的整形变量来说,整型提升是在高位补变量的符号位;而对于无符号的整形变量来说,整形提升是直接高位补0来实现的。
2.1.1 例题1🍖
问上面这个程序最终打印结果为什么是-126,是怎么算出来的呢?下面我们来细致的分析一下,如下图所示。首先char型变量a和b中分别放入截断后的3和127,然后将a+b整形提升运算后的结果进行截断操作放入char型变量c中,最后printf打印%d整形值时对变量c中的值进行按符号位的整形提升,得出的结果当然是-126啦。
2.1.2 例题2🍖
程序如上图所示,问为什么只有c是成功打印的,而a和b却是不行的呢?先拿char型变量a来说吧,首先我们知道a截断存储了十六进制数0xb6,内存补码为:10110110。但当执行到if语句的时候,a需要进行关系运算时需要进行有符号的整形提升,所以整型提升时应该在高位补符号位,结果为:11111111111111111111111110110110,与0xb6的二进制序列:00000000000000000000000010110110当然不一样呀,所以if(a == 0xb6)
判断的结果自然为假并不会打印a了呀。同理于short类型的变量b也是如此并不会被打印,而int类型的变量c由于其并不用进行整形提升,所以判断结果为真打印了c。
2.1.3 例题3🍖
很多人会觉得这道题的结果是两个1,但值得注意的是上面这个例子中sizeof(+a)计算的是+a这个表达式值的类型所占的内存空间的大小,而+a表达式的值是a进行整形提升后的结果,所以sizeof的结果为4个字节。
2.2 算数转换🍖
我们刚刚讨论的是类型小于整形的情况,而算数转换是用来处理这些大于等于整形的情况。如果某个操作符的各个操作数属于不同的类型,那么计算是无法进行下去的,除非将这些操作数全都转化为同一类型。寻常算数转换的方向:int→unsigned int→long int→unsigned long int→float→double→long double。
举个易错的例子:
肯定有人会说打印结果必然是hehe,因为sizeof(i)的结果是4嘛,必然大于-1的。可真的是这样吗?
为什么会这样呢? 这是因为在执行if(i < sizeof(i))
判断的时候隐蔽的发生了算数转换,将i的类型从int型转换成了unsigned int型,我们知道int型-1的补码在unsigned int下是一个非常大的整数必然远大于sizeof(i)计算出来的4,所以打印结果为haha。那为什么i会发生算数转换呢? 这是因为sizeof()表达式的返回值的类型其实是unsigned int型的。
三、显式类型转换🍖
显示类型转换又被称为强制类型转换,是由我们所决定该转换成什么样的类型,通常在转换时会存在存储精度的损失,所以在使用时需要谨慎。强制类型转换规则:(强制转换的类型)表达式
。
举个列子:
你会发现强制类型转换(char)a;
其实就像之前的截断操作一样,取后面的低8位然后存储到char类型的b中去,然后在printf打印的时候再按位整形提升,结果自然为-46。
这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀。