Skip to content

C语言中的数据类型与转换

考情分析

整数类型转换是选择题高频考点(2011、2016、2019、2021、2024),int/float 精度问题也多次出现(2010、2017)。核心在于理解"位模式不变,解释方式变"和"扩展/截断"两个原则。

无符号整数与有符号整数

类型编码方式8位范围
无符号整数纯二进制,所有位表示数值0255
有符号整数补码,最高位为符号位128127

同样的 8 位二进制 10000000

  • 作为无符号数解释:128
  • 作为有符号数(补码)解释:128

现代计算机统一用补码表示有符号整数,因为:零的表示唯一、加减法统一为加法、比原码多表示一个最小负数。

C 语言整数类型

类型典型位宽有符号范围无符号范围
char81281270255
short163276832767065535
int32231231102321
long32/64取决于平台取决于平台

未声明 unsigned 则默认为有符号类型。

类型转换的三种情形

1. 相同字长:位模式不变,解释方式变

c
short x = -4321;
unsigned short y = (unsigned short)x;
// x = -4321, y = 61215

x 和 y 的二进制完全相同(0xEF1F),但 x 按补码解释为 4321,y 按无符号解释为 61215

关键规律:n 位有符号数 x(补码)转为无符号数 u

  • x0u=x
  • x<0u=x+2n

所以 (unsigned short)(-1) = 1+216 = 65535

2. 短类型 → 长类型:位扩展

源类型扩展方式规则
有符号数符号扩展高位填充符号位
无符号数零扩展高位填充 0
c
short x = -4321;          // 0xEF1F
int y = x;                // 符号扩展 → 0xFFFFEF1F,值仍为 -4321

unsigned short u = 61215;  // 0xEF1F
unsigned int v = u;        // 零扩展 → 0x0000EF1F,值仍为 61215

符号扩展保持数值不变(补码的性质),零扩展保持无符号值不变。

3. 长类型 → 短类型:截断

直接丢弃高位,仅保留低位。截断可能导致数值完全改变。

c
int x = 165537;            // 0x000286A1
short y = (short)x;        // 截断为 0x86A1,解释为 -31071

165537 超出 short 的范围(3276832767),截断后语义完全不同。这种转换不会触发任何错误提示

int 与 float/double 的转换

转换方向可能发生的问题
int → float不溢出,但可能精度丢失(int 32 位有效位 > float 24 位尾数)
int → double安全(double 52 位尾数,足以精确表示 32 位 int)
float → double安全(精度和范围都扩大)
double → float可能溢出(超出 float 范围)或精度丢失
float/double → int小数部分截断(向零取整),可能溢出

:int → float 精度丢失

c
int n = 0x7FFFFFFF;   // 2147483647,二进制有效位 31 位
float f = (float)n;   // float 尾数只有 23+1=24 位,需舍入
int m = (int)f;        // m 可能不等于 n

原因:2147483647 的二进制有效位数为 31 位,超过了 float 的 24 位尾数精度,转换时会舍入。

隐式类型提升顺序

charintlongdoublefloat

混合运算时,较低类型自动转换为较高类型。

考点清单

  • 相同字长转换:位模式不变,仅改变解释方式
  • 短→长:有符号做符号扩展,无符号做零扩展
  • 长→短:截断高位,可能导致值完全改变
  • (unsigned)(-1) 得到该类型的最大值(全 1)
  • int → float:不溢出但可能丢精度(24 位尾数 < 32 位)
  • int → double:安全(52 位尾数足够)
  • float/double → int:截断小数,可能溢出

真题练习