c语言中的数据类型转化


先来看看这串诡异的代码:

int main()
{
	char a = 1;
	char b = 150;

	printf("%d", a + b);
	return 0;
}

在这里插入图片描述
从运行结果来看,1 + 150 不等于151却等于-105?是编译器出错了吗?相信我,再试一遍还是这个结果。这又是为什么呢?不急,先来看今天要介绍的第一个概念:截断。

1.截断

为什么会发生截断?我们知道,不同数据类型的字节大小是不同的,其中字符类型是最小的,只有一个字节。当我们把一个整形放进一个字符变量中,字符变量是不能存储下这么大的空间的,所以,把一个整形赋值给字符变量时,4字节的整形在被截断成1个字节后,才存进了字符变量中。

强调一下两个前提

  1. 不论是存储还是运算,整数都是以补码的形式进行的。
  2. 只有在打印时,程序才将整数的补码转化成原码,然后转换成十进制打印。

明白截断的产生原理,我们回头看看刚刚的代码,1被截断后还是1,而150的二进制表示是1001 0110,当然150是一个整形,整形二进制序列应该是 00000000 00000000 00000000 10010110,截断后变成1001 0110(补码),这个二进制数可与150差别大了,符号位是1,竟然变成了个负数,转化成原码后的二进制是1110 1010,这个二进制数表示为十进制是-106。a是1,b是-106,相加得到就是-105啦。

2. 整形提升(隐式类型转化)

概念:字符或者短整形在运算时都要先被转化为整形,这种转化被称为整形提升。

2.1 刚才的错误讲解

解释了整形提升的意思,你肯定能发现,刚刚我解释的1+150这个式子的运算过程是有问题的。150被截断后是1001 0110(补码)。由于两个数是字符类型,所以在运算时要先整形提升。

1.负数的整形提升:高位补充符号位。1001 0110在整形提升后变成11111111 11111111 11111111 10010110

2.正数的整形提升:高位补充0。0000 0001在整形提升后变成00000000 00000000 00000000 00000001

两数相加得到11111111 11111111 11111111 10010111(补码),转化成原码为 :10000000 00000000 00000000 0110 1001,这个十进制表示就是-105。其实这才是1+150 = -105的正确解释

2.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;
}

程序是否会输出abc呢?答案是只输出c。十六进制0xb6,转化成二进制并以整形表示是00000000 00000000 00000000 10110110,截断后变成10110110,之后再整形提升。显然,截断后的数是负数,与原来的数不同,自然在整形提升后,值也不同。b也同理,只有c是整形变量,没有发生截断与整形提升,所以c的值仍然是原来的值。

int main()
{
	char c = 0;
	printf("%u\n", sizeof(c));
	printf("%u\n", sizeof(-c));
	printf("%u\n", sizeof(+c));
	return 0;
}

在这里插入图片描述
c在参与运算时发生整形提升,用sizeof算出来的结果变成了4

3.寻常算术转化

不同类型的数据在一起运算时,编译系统为保证运算结果的精确度,会自动对数据进行类型转化。类型转化的规则是:把占用内存少(低级)的类型转化成占用内存多(高级)的类型。

这张图表示数据类型转换的规则,可以看到图片中有两种箭头,分别是横向与纵向的,下面我详细说说这两种箭头的区别
在这里插入图片描述

3.1 横向箭头

横向的箭头表示一种必定的类型转换,什么意思呢?比如两个char类型的数据要相加,编译系统会自动把两个char类型转换成int类型再相加。所以数据如果都是char或short类型,它们都会被编译系统转换成int类型。这种转换就是我刚刚说的整形提升。

再来看看另一个箭头,同理,两个数据如果都是float类型,它们也要先转换成double类型才能计算。因此,刚才我说的**“不同类型的数据运算时,编译系统会自动进行类型转换”**,严格来说这句话是错的。

3.2 纵向箭头

纵向箭头表示数据在经过横向的类型转换后,数据类型仍然不同时,要发生的转换。但类型的转换并不是按照箭头一步步转换的,例如一个int类型的数据和一个double类型的数据相加,编译系统直接把int转换成double再相加。

3.3 其他规则

  1. 类型转换只会影响表达式的运算结果,不会影响原变量的类型,更不会影响原变量的值。
  2. 当赋值表达式两边的运算对象不同时,也要发生类型的转换,转换的规则是:把右边表达式运算结果的类型转换为左边表达式运算结果的类型。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值