本地资料类型转换
SCHEDULE LOCAL9 个小节覆盖真题 20092025
关联考点类型转换9做相关真题 · 9 道 →
做相关真题 · 9 道选中文字可高亮或加下划线
选中文字高亮 · 下划线

类型转换

复习提示(中优先级):类型转换的关键是判断位模式是否变化,以及目标类型能否完整表示源值。

真题练习

常在选择题考查,其实就 三点:整形和浮点数的转换,不同长度类型的转换,隐式和显式的转换。

有符号整数和无符号整数

有符号整数无符号整数 之间相互转换时,二进制数据 不变,只是改变了变量(或数字)的类型。

首先需要了解 有符号整数(int)和 无符号整数(unsigned)这两个类型:

  • int:使用 补码 来存储数据。
  • unsigned:所有位,包括最高位,都用于表示数值,表示非负数。

注意:C 语言只规定各整数类型的最小宽度和相对大小,具体位宽由实现决定。常见平台的 intunsigned int 都是 32 位;实现提供相应类型时,int32_tuint32_t 可明确表示恰好 32 位的有符号和无符号整数。

这里为了方便说明,以 8 位 有符号整数无符号整数 为例:

  • 8 位 有符号整数
    • 表示的范围为 -128 ~ 127
    • 最大数为127,对应的二进制为0111 1111
    • 最小数为-128,对应的二进制为1000 0000
  • 8 位 无符号整数
    • 表示的范围为 0 ~ 255
    • 最大数为255,对应的二进制为1111 1111
    • 最小数为0,对应的二进制为0000 0000

intunsigned 进行 类型转化 时,位模式 不变,可以理解成计算机存储单元中的二进制表示没有变化,只是从程序层面阐述该二进制数据的方式变了,如下图所示:

相同八位位模式按有符号补码和无符号整数解释时的数值变化

整数和浮点数

在计算机中,整形(short, int, long)和 浮点数(float, double)之间可以相互转换,但是在转换的过程中可能出现 精度丢失数据溢出

整数转浮点数

如果一个整数被转换为浮点数,其结果是否会产生 精度丢失 取决于整数的大小是否超过浮点数可以精确表示的整数范围。 但当整数足够大时,转换可能导致 精度损失

例如 IEEE 754 单精度 floatfrac 字段为 23 位,加上隐含的最高位后,有效精度为 24 位。因此区间 [224,224][-2^{24},2^{24}] 内的每个整数都能被精确表示,若一个 int 的值在这个范围内,转换为 float 时不会丢失精度。

超出这个范围并不意味着一定无法精确表示:较大的 2 的整数次幂及某些低位为 0 的整数仍可精确表示。能否精确表示取决于该数量级下相邻浮点数的间隔;不能落在可表示点上的整数会被舍入。

浮点数转整数

浮点数 被转换为 整数 时,小数部分会丢失,因为 整数 不能表示小数。

此外,如果 浮点数 超出了 整形 的表示范围,转换可能会 溢出 或产生未定义行为(取决于语言)。

不同长度的类型转换

类型 C 标准规定的最小位数 常见 ILP32 常见 LP64 常见 LLP64
char 8 8 8 8
short 16 16 16 16
int 16 32 32 32
long 32 32 64 32
long long 64 64 64 64
float 32 32 32
double 64 64 64

其中 ILP32 常见于 32 位系统,LP64 常见于 64 位 Unix-like 系统,LLP64 常见于 64 位 Windows。表中浮点位宽是主流 IEEE 754 实现的常见值。

总结一下不同长度的 整数浮点数类型转换 规则:

  • 整数和整数
    • 较小的整数类型转换为能覆盖其全部取值范围的较大整数类型时,无符号数进行零扩展,有符号补码进行符号扩展,不会丢失数值。
    • 较大的 整数类型 被转换为较小的 整数类型 时,高位会被自动截断,可能有数据丢失。
  • 浮点数和浮点数
    • float 转为 double 时,不会有 精度丢失double 转为 float 时,可能有 精度丢失
整数拓宽、整数截断以及单精度和双精度转换的位宽变化

shortint 的类型转化为例说明:

/* 将 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 然后进行计算

在一个表达式中混合使用 intfloat 时,C 语言通常会把 int 转换为 float 后再计算。这里的“类型等级更高”不保证数值精度一定更高:大整数转为 float 仍可能被舍入。

显式类型转换

也可以使用 类型转换运算符 显式地转换一个类型为另一个类型。

/* 显式类型转换 */
int i = 5;
float f = 3.2;
int result = (int)f + i; // f 被显式转换为 3,然后与 i 相加

显式类型转换 会按照你指定的方式进行,在此过程中可能会发生 精度缺失

位模式、数值解释与转换风险

同一组 ww 位的比特可以有不同解释。按无符号整数解释时范围是 002w12^w-1;按补码有符号整数解释时范围是

2w1 到 2w11.-2^{w-1}\ \text{到}\ 2^{w-1}-1.

因此“重新解释位模式”和“进行数值转换”不是一回事。最高位为 1 的位模式按无符号解释是较大的正数,按补码解释则可能是负数;没有移动任何 bit,数值含义却已改变。混合有符号、无符号运算时,应先按语言或题设的提升规则统一类型,再比较或计算,不能仅凭变量原来的数学值判断结果。

扩大整数位宽时,无符号数通常在高位补 0,有符号补码数通常做符号扩展,即复制原符号位;两种扩展都应保持原数值。缩小位宽时,高位被截去,结果可能溢出原类型可表示范围;对无符号位模式可看作模 2w2^w 保留低位,而有符号结果的具体语义还需遵循 ISA 或语言规则。做位扩展题时先写出原位模式,再写新增或保留哪些位,比直接心算十进制更不易出错。

整数转浮点数需要把值规格化为尾数和指数;当整数有效位超过浮点尾数字段能精确表示的范围时,低位会按舍入规则丢失。浮点数转整数通常去掉小数部分,但 NaN、无穷大或超出目标整数范围时的结果取决于处理器和语言环境,不能一概说成“截断后一定得到某个正常整数”。转换题应分别检查符号、范围、精度和舍入四件事。