目录
引入
类型转换:
当使用一种类型代替另外一种类型进行操作时或者存在两个不同类型的对象进行操作时,首先就得进行类型的转换。而类型转换的方式一般可分为
-
隐式类型转换(自动类型转换)
-
显示类型转换(强制类型转换)
那么他们究竟有何不同呢?
隐式类型转换
整型提升
定义:
C语言中字节数少于整型字节数的数据类型在进行整型运算时,该类型的数据会被默认转为整型数据。
理解:
运算器(ALU),其操作对象的字节大小被要求至少是int的字节数。数据在被运算时,数据并不是直接在ALU上存储的,而是存储在CPU的寄存器(register)中,而通用寄存器的字节大小与ALU操作数的字节大小保持一致。针对小于4byte的数据类型,会默认转化为整型数据
情况:
在数据类型为char(1byte)/short(2byte)时,需要考虑整型提升。
char:
当数据在-128~127之间时,可以用8bits(1byte)表示,不需要整型提升。但当数据超过时候则需要。
unsigned char:
当数据在0~255之间,不需要考虑整型提升。
转化方法:
-
无符号数(unsigned char):低位不变,高位补符号位;
-
有符号数(char):低位不变,高位补0。
例【1】
int main()
{
char a=3;
char b=127;
char c=a+b;
printf("%d",c);
}
打印的结果为-126。
理性分析:
截断存入a,b
a的补码为0000 0011
b的补码为0111 1111
运算时,整型提升:
a的补码为0000 0000 0000 0000 0000 0000 0000 0011
b的补码为0000 0000 0000 0000 0000 0000 0111 1111
c的补码为0000 0000 0000 0000 0000 0000 1000 0010
截断
c的补码为1000 0010
输出
c的数据类型为char而非unsigned char,所以用有符号的整型提升方式
c的补码为1111 1111 1111 1111 1111 1111 1000 0010
c的反码为1111 1111 1111 1111 1111 1111 1000 0001
c的原码为1000 0000 0000 0000 0000 0000 0111 1110
针对原码,按照%d,即为有符号位的数字
c对应的数字为-126
例【2】
int main()
{
char a=255;
printf("%d",a);//-1
printf("%u",a);//4294967295
}
截断存入
1111 1111
输出时,按有符号类型整型提升
255的补码1111 1111 1111 1111 1111 1111 1111 1111
255的反码1111 1111 1111 1111 1111 1111 1111 1111
255的原码1111 1111 1111 1111 1111 1111 1111 1111
按%d输出-1
按%u输出4294967295
隐式类型转换总结:
-
存入数据时(char a=-1;char b=255):存入补码,按照数据类型进行截断,例如char,则只保留8个bit
-
计算数据时(char c=a+b):按照原数据类型进行整型提升,然后用补码相加减,再次截断存入(8位)
-
输出数据时(printf("%d/%u")):按照原数据类型进行整型提升,经过反码转化为原码(32位),最后根据%d/%u输出数据
算数转换
上面提到的均为所占内存大小小于int类型的情况?那其他情况呢?
寻常算数转换的方向:
double ←── float 高
↑
long
↑ unsigned
↑ int ←── char,short 低
例【3】
int main()
{
int i=-1;
if(i<sizeof(i))
{
printf("-1<4?");
}
if(i>sizeof(i))
{
printf("-1>4?");
}
}
让人意外的是最后输出的结果是-1>4?
这是什么原因呢?我们分析一下:
- 第一感觉最有可能出问题的就是这里的sizeof。
- sizeof这个运算符的返回类型是size_t,是unsigned int 的一种。所以在sizeof(i)时,i从int转化成为了unsigned int。
- -1的补码是一长串1,所以可想而知转化为无符号类型(unsigned int)数据会变得非常之大,因此这个结果也就合理了。
显式类型转换
格式:(强制转换的类型)表达式
int main()
{
int a=(int)3.14;
printf("%d",a);
最后输出结果位3
}
再看下面这个例子,是否强制类型转换也会影响最后的结果:
-
mean1:17/5 中两个操作数均为整型,最后的结果是一个去除小数部分的整数3,再用float类型输出,变为3.000000
-
mean2:其中的17转化为double类型,实际上是17.000000/5结果也就自然会多出这个0.400000
以上就是本篇博客的全部内容