【C语言初阶】隐式类型转换
文章目录
1 隐式类型转换
C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。
1.1 整型提升
为了获得这个精度,表达式中的字符型和短整型操作数在使用之前会被转换为普通整型,这种转换称为整型提升。
1.2 整型提升的意义
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般是一个
int
的字节长度,同时也是CPU中通用寄存器的长度。
因此,即使两个char类型的对象相加,在CPU执行时也要事先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接进行相加的运算。所以,表达式中各对象的长度可能小于
int
长度的整型值,都必须先转换为int
或unsigned int
,然后才能送去CPU执行型运算。
1.3 示例1
代码示例:
#include<stdio.h>
int main()
{
//整型提升示例1
char a = 0, b = 0, c = 0;
a = b + c;
//在执行b+c运算时,先将b和c的值提升为整型,然后再进行加法运算
//加法运算执行完后,由于a是字符型,赋的值为整型,存储时会发生截断
return 0;
}
解释说明:
1 进行加法运算时,如果操作数是 char
类型的,就会发生整型提升。
2 整型数值赋给字符型变量时会发生截断。
1.4 如何进行整型提升?
整型提升是按照变量的数据类型的符号位来进行提升的。
1.4.1 负数的整型提升
代码示例:
#include<stdio.h>
int main()
{
//负数的整型提升
char ch = -1;
//00000000 00000000 00000000 00000001 -- 1的补码(原码)
//10000000 00000000 00000000 00000001 -- -1的原码
//11111111 11111111 11111111 11111110 -- -1的反码
//11111111 11111111 11111111 11111111 -- -1的补码
//int型数据存放到char型变量中,会发生截断,取低8位二进制
//11111111 -- 补码形式,符号位为1
//如何进行整型提升
//char为有符号的char,在整型提升的时候,高位补充符号位,此处符号位为1
//11111111 11111111 11111111 11111111 -- 整型提升后的结果,是一个负数的补码
return 0;
}
解释说明:
1 在整型提升时,高位用符号位的值来填充。
1.4.2 正数的整型提升
代码示例:
#include<stdio.h>
int main()
{
//正数的整型提升
char a = -1;
//11111111 11111111 11111111 11111111 -- -1的补码
//整型值存储到char型变量时会发生截断:
//11111111
signed char b = -1;
//11111111
unsigned char c = -1;
//11111111
printf("a = %d,b = %d,c = %d\n", a, b, c);//-1 -1 255
//a为有符号的char,在整型提升的时候,高位补充符号位,此处符号位为1
//整型提升
//11111111 11111111 11111111 11111111 负数的补码
//11111111 11111111 11111111 11111110 负数的反码
//10000000 00000000 00000000 00000001 负数的原码 -- -1的原码
//
//b为有符号的char,在整型提升的时候,高位补充符号位,此处符号位为1
//整型提升
//11111111 11111111 11111111 11111111 负数的补码
//11111111 11111111 11111111 11111110 负数的反码
//10000000 00000000 00000000 00000001 负数的原码 -- -1的原码
//
//c为无符号的char,无符号数进行整型提升的时候,高位补0
//整型提升
//00000000 00000000 00000000 11111111 正数的补码
//00000000 00000000 00000000 11111111 正数的原码 -- 255的原码
return 0;
}
解释说明:
1 无符号数在进行整型提升的时候,高位补0。
1.5 示例2
代码示例:
#include<stdio.h>
int main()
{
//整型提升示例2
char a = 0xb6;
//0xb6是一个十六进制数,每4位二进制数表示1个十六进制数
//b 6
//1011 0110
//00000000 00000000 00000000 10110110 -- 0xb6的补码(原码)
//整型值存储到char型变量时会发生截断,一个char变量占8个bit位
//10110110 -- 补码形式,符号位为1
short b = 0xb600;
//0xb600是一个十六进制数,每4位二进制数表示1个十六进制数
//b 6 0 0
//1011 0110 0000 0000
//00000000 00000000 10110110 00000000 -- 0xb600的补码(原码)
//整型值存储到short型变量时会发生截断,short型为16个bit位
//10110110 00000000 -- 补码形式,符号位为1
int c = 0xb6000000;
//10110110 00000000 00000000 00000000 00000000 -- 0xb6000000的补码(原码)
//进行表达式计算时,变量a的类型是char类型,此时会发生整型提升
if (a == 0xb6)
{
//a存储的值:10110110
//10110110 -- 补码形式,符号位为1
//a为有符号的char,在整型提升的时候,高位补充符号位,此处符号位为1
//
//发生整型提升:
//11111111 11111111 11111111 10110110 -- 整型提升后的结果,是一个负数的补码
//00000000 00000000 00000000 10110110 -- 0xb6的补码(原码)
//结果明显不相同,判断为假
//
printf("a\n");//不打印
}
if (b == 0xb600)
{
//b存储的值:10110110 00000000
//10110110 00000000 -- 补码形式,符号位为1
//b为有符号的short,在整型提升的时候,高位补充符号位,此处符号位为1
//
//发生整型提升:
//11111111 11111111 10110110 00000000 -- 整型提升后的结果,是一个负数的补码
//00000000 00000000 10110110 00000000 -- 0xb600的补码(原码)
//结果明显不相同,判断为假
//
printf("b\n");//不打印
}
if (c == 0xb6000000)
{
//c为整型,不发生整型提升
//
printf("c\n");//打印输出
}
//最终打印输出结果为:c
return 0;
}
解释说明:
详解见上述代码中的注释内容。
1.6 示例3
代码示例:
#include<stdio.h>
int main()
{
//整型提升示例3
char c = 1;
printf("%u\n", sizeof(c));//1
printf("%u\n", sizeof(+c));//4
printf("%u\n", sizeof(-c));//4
//sizeof求值返回的是size_t类型的值
//size_t <==> unsigned int
//%u -- 以十进制形式打印无符号整数
return 0;
}
解释说明:
1 +c
和 -c
都是表达式,会进行计算求值;而 c
的类型为 char
,表达式求值时会发生整型提升。
对操作数进行整型提升后,sizeof
计算的值就为 int
型的值。
2 c
是 char
类型的变量,如果参与了表达式运算,就会发生整型提升。
2 算术转换
如果某个操作符的各个操作数属于不同的数据类型,那么只有较低数据类型向较高数据类型进行隐式类型转换,彼此间才能进行运算。
2.1 寻常算术转换
示例:
long double
double
float
unsigned long int
long int
unsigned int
int
说明:
1 上述所示数据类型,如果某个操作数的类型排名较低,那么首先要转换为另一个操作数的类型,然后再进行运算。
2 上述类型,由低向高( int -> long double
)进行算术转换。
注意:
应避免较高类型向较低类型的转换。
float f = 3.14f;
int num = f;//隐式类型转换,会丢失精度
总结:
本节介绍了隐式类型转换中的整型提升和算术转换,同时给出了相关代码以及详细注释。
感谢您的阅读!如有任何错误,欢迎您的批评指正!