类型转换
有符号整数和无符号整数
当有符号整数和无符号整数之间相互转换时,二进制数据不变,只是改变了变量(或数字)的类型。
首先需要了解有符号整数(int)和无符号整数(unsigned)这两个类型:
int
:使用补码来存储数据。unsigned
:所有位,包括最高位,都用于表示数值,表示非负数。
注意
在现在的 64 位计算机中,一般 int 表示 32 位有符号整数,unsigned 表示 32 位无符号整数。 由于 int 和 unsigned 在不同体系计算机中行为不同,所以 C 语言库中也自带 int32_t、uint32_t 这种类型来表示特定位数的有符号和无符号整数,并在各计算中行为一致。
这里为了方便说明,以 8 位有符号整数和无符号整数为例:
- 8 位有符号整数
- 表示的范围为
-128 ~ 127
- 最大数为
127
,对应的二进制为0111 1111
- 最小数为
-128
,对应的二进制为1000 0000
- 表示的范围为
- 8 位无符号整数
- 表示的范围为
0 ~ 255
- 最大数为
255
,对应的二进制为1111 1111
- 最小数为
0
,对应的二进制为0000 0000
- 表示的范围为
当 int
和 unsigned
进行类型转化时,位模式不变,可以理解成计算机存储单元中的二进制表示没有变化,只是从程序层面阐述该二进制数据的方式变了。
当我们将 8 位的有符号整数 -128 转化为无符号整数时,其值变成了 128。
整形和浮点数
在计算机中,整形(float, double)和浮点数(int, long)之间可以相互转换,但是在转换的过程中可能出现 精度丢失 或 数据溢出。
整形转浮点数
如果一个整数被转换为浮点数,其结果是否会产生精度丢失取决于整数的大小是否超过浮点数可以精确表示的整数范围。 但当整数足够大时,转换可能导致精度损失。
比如对于 float 类型,其尾数为 23 位,它可以精确表示的整数范围为 $(-2^{24}, 2^{24})$,如果一个 int 类型的数字在这个范围内,则将其转换为 float 时不会丢失精度。
但是如果 int 类型数字超出这个范围且低 8 位不全为 0 的话,则将其转换为 float 会有精度丢失。
浮点数转整数
当浮点数被转换为整数时,小数部分会丢失,因为整数不能表示小数。
此外,如果如果浮点数超出了整形的表示范围,转换可能会溢出或产生未定义行为(取决于语言)。
不同长度的类型转换
类型 | 最小位数 | 常见位数(32 位系统) | 常见位数(64 位系统) |
---|---|---|---|
char | 8 位 | 8 位 | 8 位 |
short | 16 位 | 16 位 | 16 位 |
int | 16 位 | 32 位 | 32 位 |
long | 32 位 | 32 位 | 64 位 |
long long | 64 位 | 64 位 | 64 位 |
float | - | 32 位 | 32 位 |
double | - | 64 位 | 64 位 |
总结一下不同长度的整数和浮点数的类型转换规则:
- 整数和整数
- 较小的整数类型被转换为较大的整数类型时,高位会被自动填充为 0 或 1,不会有数据丢失。
- 较大的整数类型被转换为较小的整数类型时,高位会被自动截断,可能有数据丢失。
- 浮点数和浮点数
float
转为double
时,不会有精度丢失,double
转为float
时,可能有精度丢失。
以short
和int
的类型转化为例说明:
/* 将 short 转为 int */
short s = 0x1234;
int i = s;
// 高 16 位被填充为 0
// i = 0x00001234
/* 将 int 转为 short */
int i = 0x12345678;
short s = i;
// 高 16 位被截断
// s = 0x5678
类型转换
在编程中,类型转换指的是将一种数据类型转换为另一种数据类型。主要分为两种:
- 隐式类型转换(Implicit Type Conversion)(也称为类型提升,Type Promotion)
- 显式类型转换(Explicit Type Conversion)(也称为强制转换,Type Casting)
隐式类型转换
在 C 语言中,当算术运算、赋值和比较表达式中涉及的多个变量类型不同时,如果没有显式指定类型,编译器会自动进行类型转换。
/* 隐式类型转换 */
int i = 5;
float f = 2.5;
float result = i + f; // i 被隐式转换为 5.0 然后进行计算
你在一个表达式中混合使用 int
和 float
时,C 语言会自动进行类型转换以使得表达式可以正确计算。通常情况下,低精度类型会被提升到高精度类型,即 int
会被转换为 float
。
显式类型转换
也可以使用类型转换运算符显式地转换一个类型为另一个类型。
/* 显式类型转换 */
int i = 5;
float f = 3.2;
int result = (int)f + i; // f 被显式转换为 3,然后与 i 相加
显式类型转换会按照你指定的方式进行,在此过程中可能会发生精度缺失。