Appearance
题目
有如下 C 语言程序段
c
short si = -32767;
unsigned short usi = si;执行上述两条语句后,usi 的值为( )。
错因
A
把"赋值"想成了"按数值含义复制"——以为 usi 也能存负数。但 unsigned short 表示范围是 ,根本不能保存 。C 语言里有符号 → 无符号的转换是按位重新解读(位模式不变,重新查无符号编码表),不是数值意义上的"保留"。
B
以为转换是"取绝对值"。这是把 unsigned 当成"去掉符号位"的浪漫想象——实际上没有这种规则,CPU 不会替你做绝对值;位模式怎么样就怎么解读。
C
把 的补码错算成 了。但 是 的补码(短整型最小值),不是 的补码。把这个位模式当无符号读 = ,所以选 C 的人差了 1:本质上是补码取反加 1 那一步漏了 "+1"。
总解析
第一步:写出 -32767 的 16 位补码
求 的补码:把 按位取反再加 1:
| 步骤 | 二进制位串 |
|---|---|
| 原码 | 0111 1111 1111 1111 |
| 按位取反 | 1000 0000 0000 0000 |
1000 0000 0000 0001 |
所以 si 在内存里的位模式是 1000 0000 0000 0001。
第二步:把 si 的位模式赋给 usi(位模式不变,类型重新解读)
C 标准规定:在同宽度有符号 ↔ 无符号转换时,底层位模式不动,只是按目标类型的编码规则重新解读。所以 usi 也是 1000 0000 0000 0001。
第三步:把 1000 0000 0000 0001 当无符号 16 位整数读
最终答案是 D(32769)。
关键易错点速查:
| 错误想法 | 实际规则 |
|---|---|
| "无符号不能存负数,应该报错或裁剪" | 转换不报错,按位重新解读 |
| "应该取绝对值 32767" | 没有这种规则 |
| " 的补码 = " | 是 ; 末位有 "" |
通用结论:负的 short 转 unsigned short 的结果 = ,本题 直接得答案,可作快速校验。