强制类型转换不改变二进制位模式,仅改变解释方式;有符号转无符号时负数因符号位被当数值位而变成大正数,如-12345(short)→53191(unsigned short)。

强制类型转换本身不改变内存中的二进制位模式,只改变对这些位的解释方式。溢出和符号位变化不是“发生”在转换动作里,而是源于目标类型的表示能力不足或符号规则不同——关键看源值是否落在目标类型的合法取值范围内,以及系统如何解读最高位(符号位)。
有符号转无符号:负数变大正数
当一个负的有符号整数被强制转为同宽度无符号类型时,位模式不变,但最高位不再被视为符号位,而是数值的一部分。结果是原负数的补码形式被当作纯二进制数解读,得到一个很大的正整数。
- 例如:
short v = -12345在内存中是1100 1111 1100 0111(16位补码),转成unsigned short后仍为该位串,但解释为十进制 53191 - 常见风险:
if (x 判断失效,因为 <code>(unsigned int)x永远 ≥ 0 - 防范:转换前显式检查符号,或用更安全的抽象(如
size_t配合非负断言)
无符号转有符号:超限值变负数
当无符号数大于目标有符号类型能表示的最大正数时,其位模式被按有符号规则重新解释,最高位为1 → 视为负数。这不是“计算错误”,而是补码系统的自然结果。
- 例如:
unsigned u = 4294967295u(32位全1),转成int后位模式仍是1111...1111,解释为十进制 −1 - 注意:若无符号值 ≤
INT_MAX(如2147483647),则转换后数值不变 - 风险点常出现在函数参数传递中,比如把
size_t的大值转int传给旧API,导致逻辑反转
宽转窄:高位截断引发静默失真
从宽整型(如 int、long)转窄整型(如 short、char)时,只保留低字节,高位直接丢弃。这会导致数值跳变,且不报错。
- 例如:
int a = 100000(二进制末16位为10000110 10100000),转short后变成 −31072 - 截断还可能破坏符号扩展逻辑:原本
short负数提升为int是安全的,但反向操作不可逆 - 建议:启用编译器警告(如
-Wconversion),或用int16_t等定宽类型明确意图
浮点转整数:舍入与截断不可逆
浮点数转整数不是位模式重解释,而是数值映射:小数部分被截断(朝零取整),且可能超出整型范围。
-
float f = 3.9f;→(int)f得 3;f = -3.9f;→ 得 −3 - 若浮点值超出目标整型可表示范围(如
1e10f转int),行为未定义(UB) - 安全做法:先用
isfinite()和范围比较(如f = INT_MIN)再转换









