【C语言学习记录】(五)——操作符详解⑥——表达式求值 和 隐式类型转换

一、表达式求值

  表达式求值的顺序一部分是由操作符的优先级和结合性决定。同样,有些表达式的操作数在求值过程中可能需要转换为其他类型。

int main()
{
	int a = 3;
	int b = 5;
	int c = a + b * 7;//先执行b*7
	
	return 0;
}

二、隐式类型转换

C的整型算数运算总是至少以缺省(shěng)值类型的精度来进行的。为了获得这个精度,表达式中的字符char和短整型short操作数在使用之前被转换成为普通整型int,这种转换称为整型提升

实例①

char a, b, c;
//···
a = b + c;

  a,b,c是char类型,在内存中占据1个字节没有达到一个普通整型int的大小(4个字节)。在计算a = b + c时,我们需要把b和c的值提升为普通整型int,变成4个字节,然后再执行加法运算。加法运算完成后,我们发现b+c的结果是4个字节,而a是1个字节,a中放不下计算结果,所以结果将被截断,然后在存储于a中。
截断:在本题中我们将4个字节的数据存放到1个字节中,我们只保留最低的那个字节中的内容,把剩余的3个字节中的内容扔掉。
整型提升的意义:
  表达式的整型运算要在CPU的相应运算器件内运行,CPU内整型运算器(ALU)的操作数的字节长度一般是int的字节长度,同时也是CPU的通用寄存器的长度。
  因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
  通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或者unsigned int,然后才能送入CPU去执行运算。
  也就是说在运算时,不管是char类型还是short类型都没有达到一个int类型的大小,但是CPU又是以整型的方式来计算的。此时若我们把charshort提升为整型int,那么计算精度会高一些。(不转白不转,不升白不升)

1.整型如何提升?

实例②

int main()
{
	char a = 3;  //二进制序列:00000000000000000000000000000011
	char b = 127;//二进制序列:00000000000000000000000001111111
	char c = a + b ;
	//发现a和b都是char类型,都没有达到一个int的大小
	//这里就会发生整型提升
	printf("%d\n", c);
	return 0;
}

运算结果:在这里插入图片描述
  首先,我们发现a和b是char类型,我们把3放到a里,127放到b里,a+b的结果放到c里。数据在内存中以补码的形式存储,正数的原码、反码和补码是一样的,负数的原码、反码和补码是互不相同的。
(1)原码: 将数字转换成二进制,并在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
(2)反码: 将原码符号位不变,其他位依次按位取反。
(3)补码: 符号位不变,反码加一得到补码。
然后,3的二进制序列是:00000000000000000000000000000011
  127的二进制序列是:00000000000000000000000001111111

  我们把3的二进制序列放到a中,而a是一个char类型,只能放8个比特位,所以会发生截断,只存储最小的8个比特位,即:00000011
  同理:b也只能存储最小的8个比特位,即:01111111。27是128(二进制:10000000),所以127是01111111。
此时a+b就是00000011+01111111,而这两个都是char类型,没有达到int类型的大小,所以这里就会发生整型提升
整型提升是按照变量的数据类型的符号位来提升的。
  我们让a发生整型提升,a是char类型,char是有符号的char。所以这8个bit位的最高位是符号位,而a和b的符号位都是0,表明他们都是正数,整型提升时高位补的都是0。
提升完后:
a的二进制序列:00000000000000000000000000000011
b的二进制序列:00000000000000000000000001111111
   相加结果为:00000000000000000000000010000010
(1)a和b的二进制序列最末位的都是1,1+1=2,余0进1,则结果的二进制序列最后一位为0。
(2)进1后,倒数第二位上是1+1+1=3,余1进1,则结果的二进制序列倒数第二位为1。
(3)进上来的1和a、b的二进制序列的倒数第三位上的0和1相加,1+1+0=2,余0进1。以此类推,直至倒数第8位,此时为1+0+0=1,所以余1。再往前a和b的二进制序列对应位的相加结果均为0。
  加完之后的二进制序列00000000000000000000000010000010要放到c里面去,而c是一个char类型,所以只能放最小的8个比特位,即10000010
  此时的a、b、c的二进制序列分别是:

名称二进制序列
a00000011
b01111111
c10000010

  c是char类型,但printf("%d\n", c);它是以整型打印的,所以c也需要进行整型提升。
  c整型提升后:11111111111111111111111110000010 (补码),内存中的数字用补码计算。符号位是1,则代表c是负数。打印出来,我们看到的数字应该是原码。
原码取反,+1是补码;补码-1取反是原码
11111111111111111111111110000010 ——补码
11111111111111111111111110000001 ——反码
10000000000000000000000001111110 ——原码
  26+25+24+23+22+21
=64+32+16+8+4+2
=126,前面的符号位是1,则c为-126。

2.整型提升总结

(1)负数的整型提升

二进制序列是补码,高位补充符号位,即为1

(2)正数的整型提升

原、反、补均可,高位补充符号位,即为0

(3)无符号整型提升

如:unsigned char,unsigned short两种类型是无符号的,高位补0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值