有符號數和無符號數的移位區別

(下面所有的測試爲Linux平臺,gcc編譯器)

#include <stdio.h>

#include <stdlib.h>


int main ()

{

    int a = 0x80000000;

    unsigned int b = 0x80000000;


    printf("a right shift value is 0x%X\n", a >> 1);

    printf("b right shift value is 0x%X\n", b >> 1);


    return 0;

}

輸出結果爲

[root@Lnx99 test]#./a.out

a right shift value is 0xC0000000

b right shift value is 0x40000000

爲什麼結果不同呢?

查看彙編代碼

Dump of assembler code for function main:

0x080483c4 : push %ebp

0x080483c5 : mov %esp,%ebp

0x080483c7 : and $0xfffffff0,%esp

0x080483ca : sub $0x20,%esp

0x080483cd : movl $0x80000000,0x18(%esp)

0x080483d5 : movl $0x80000000,0x1c(%esp)

0x080483dd : mov 0x18(%esp),%eax

0x080483e1 : mov %eax,%edx

0x080483e3 : sar %edx

0x080483e5 : mov $0x80484e4,%eax

0x080483ea : mov %edx,0x4(%esp)

0x080483ee : mov %eax,(%esp)

0x080483f1 : call 0x80482f4

0x080483f6 : mov 0x1c(%esp),%eax

0x080483fa : mov %eax,%edx

0x080483fc : shr %edx

0x080483fe : mov $0x8048501,%eax

0x08048403 : mov %edx,0x4(%esp)

0x08048407 : mov %eax,(%esp)

0x0804840a : call 0x80482f4

0x0804840f : mov $0x0,%eax

0x08048414 : leave

0x08048415 : ret

End of assembler dump.

其中紅色代碼對應的是a>>1,sar爲算術右移,使用符號位補位,在這裏補的全是1.

藍色代碼對應的是b>>1,shr爲邏輯右移,使用0補位。


在平時的工作中,一般情況下,我們所期待的移位操作應該爲邏輯右移,所以在使用移位操作時,一定要注意操作數的類型,一定要保證爲無符號數。這樣結果纔是我們所期待的結果。


查了查資料,根據大多數的說法。C標準沒有規定有符號數的右移如何處理。那麼對於有符號數的右移處理,就由編譯器決定。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章