漫谈~符号对无符号整形的影响

一直从课本中知道,当一个无符号类型,比如unsigned char a = 0xA5; a = ~a>>4;

结果如何?

一开始按着以前的知识整理得~a 为 0x5A, 在左移4位,根据无符号类型的移位准则,理想当然的认为最后结果是0x05;

可是天不随人愿,当我们把这段代码在机器上跑的时候,结果是0xF5.

一开始一直不理解,无符号整形移位不是前面补0吗,怎么感觉现在是补1。于是我开始怀疑编译器有问题,于是进行了如下实验:

实验代码如下:

int main(int argc, char** argv) {

    unsigned char  a = 0xA5, a1;
    unsigned short b = 0xA5 ,b1;
    unsigned int c = 0xA5, c1;
    printf("%x,%x,%x\n", a, b,c);
    
    a1 = ~a;
    b1 = ~b;
    c1 = ~c;
    a1 >>= 4;
    b1 >>= 4;
    c1 >>= 4;
    printf("%x,%x,%x\n", a1, b1,c1);
    
    a = ~a>>4;
    b = ~b>>4;
    c = ~c>>4;
    printf("%x,%x,%x\n", a, b,c);
    return 0;
}

  一运行发现结果是:

 

 

于是开始追踪汇编源码,发现当进行~操作时,在32机器上,那些低于4个字节的类型,取非之后自动变为int型,如下:

上图可知,当~a后在寄存器eax的值为0xFFFFFF5A,然后左移的话是直接对寄存器eax左移,那时候当做int左移,而且因为转int后为有符号类型,

上面可知eax是一个负值,左移4位为0xFFFFFFF5,然后mov byte ptr [a], al, 这时候a = 0xF5, 而不是我们想的0x05.

但是当我们先a1 = ~a时:

可知eax也是0XFFFFFF5A,但是AL = 0x5A,所以对a1赋值后a1 = 0x5A, 由于a1是无符号类型,左移4为0x05。

同理unsigned short类型也是一样。

对于unsigned int 类型,当c = 0xA5时,发现结果都是0x0FFFFFF5(上面输出前面的0省略了), 可知对于满32位的值,取非操作之后还是无符号类型。

而少于32位的无符号类型,取非之后被当做一个有符号int值进行位移操作了。

posted on 2013-06-11 19:20  冰尨  阅读(131)  评论(0)    收藏  举报

导航