unsigned 和 signed 之间的赋值转化
unsigned 和 signed 之间的转化赋值非常容易被弄错,例如经典的 (-1)和 0xFFFFFFFF比较。如下:
unsigned short i = -1;
if (0xFFFFFFFF == i) {
..... ; /* this will not be executed forever ! */
}
鉴于经常被弄错,我现在总结一下,转化规则,有几个情形:
1.同位宽,同符号 2.同位宽,不同符号,这个情况,就是几条mov dword [xxxx],xxxx 语句,所以操作的必然就是机器数,-1 即为 0xFFFFFFFF; 因此我们发现,不论是 : unsigned a = -1; int b = a; 还是 int a = -1; unsigned b = a; 结果都是机器数,这里都是 0xFFFFFFFF。 3. 不同位宽,但同符号: <1> 大转小,必然是 mov xxx,word [ .... ]这种,就是取低16位 <2> 小转大,必然有符号扩展咯!,全补1,和全补0,比如 short a = 1234; int b = a ; b 就是 0x00001234 short a = -0x1234; int b = a; b 就是 0xFFFF1234,就是 movsx 符号扩展了,参见杨季文《80x86...》 4. 不同位宽,不同符号; 从前面的测试来看,可以直接从机器数推算出来,不同位宽的转化即为 dword 和 word 或者 byte 之间的相互 mov ,而不同符号之间的数据mov 即为补码的mov 操作。因此可以大胆推算出: <1> unsigned short ---> int : 直接将 unsigned short 拷贝到 int 的低16位即可,高16全为0,所以得到的值就是 unsigned short 的值。 <2> int --> unsigned short : 将 int 以补码形式表示,低16位全部mov 给unsigned short 即可,得到的数值就是 以int以unsigned 表示的数值的低16位。 <3> unsigned int --> long ;即为unsigned 数值 <4> long ---> unsigned ;同<3>
<5--n> ...........
我们不难得出结论,unsigned 和 signed 之间相互之间的相互转化,以汇编的眼光来看,只有一种处理:取补码,mov 操作。