1 |
|
这是两段很简单的代码,我就以第二段代码为例。在计算机中,负数是以补码来存储的。
C 语言中常量整数 -1 的补码表示为 0xFFFFFFFF
。截取后面 16 位 FFFF
赋值给变量 a(unsigned short)。此时 a = 0xFFFF。
(a 没有符号位,0xFFFF 转换为十进制为 65535)
a 又将 0xFFFF
,直接赋值给 short b。 此时 b = 0xFFFF。
(但是要注意,b是有符号的,0xFFFF 转换为十进制为-1)。
执行 printf("%d %d", a, b)
的时候,要将 a 和 b 的值先转换为 int 型(相当于 signed int,有符号型):
- unsigned → signed:a 没有符号所以转为 int 型为
0x0000FFFF
,即65535
- signed → signed:b 有符号所以转为 int 型为
0xFFFFFFFF
,即-1
再看一个例子:
1 | int main(int argc, char *argv[]) |
因为在 printf 中的 %d 会将其强制转换成有符号整形数 -1,所以如果用 cout 输出 a,结果应该是 4294967295,或是用 %u 格式输出。
只要记住:看原来被转换的是 signed 还是 unsigned。
unsigned → signed 的时候,是直接复制到低位,高位填0。如果 signed 类型位数不够,只直接装载 unsigned 低位。
signed → unsigned 的时候,也是将补码直接复制到低位,高位填符号位。如果 unsigned 位数不够,只直接装载 signed 低位。
编译器里面有标准的转换,这个是在整型运算的时候出现。标准转换的规则是:短的的向长的转;有符号的向无符号的转。如果被转换的数据比转换后的数据要长的话,转换可能会丢失高位数据。通常,编译器会给出警告。
如:
1 | int a = -1; |
最终的展示结果还是要看 %u 还是 %d。无符号整数和有符号整数进行运算,是有符号整数向无符号整数靠齐。
从短到长依次为:short → unsigned short → int → unsigned int。