1. 程式人生 > >C:位運算之 左移運算和右移運算

C:位運算之 左移運算和右移運算

C:位運算之 左移運算(<<)和右移運算(>>)

在C中,位運算包含兩種移位運算:

左移運算:<<

右移運算:>>

左右位移運算,在數值為無符號和有符號情況下具有不同行為。

有符號左右位移運算
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// signed int左移
void si_left_shift(signed int si, int n)
{
    printf("%08X << %d: %08X\n"
, si, 4, si << n); } // signed int右移 void si_right_shift(signed int si, int n) { printf("%08X >> %d: %08X\n", si, 4, si >> n); } int main() { // positive signed int signed int psi = 0x12345678; si_left_shift(psi, 4); si_right_shift(psi, 4); // negative signed int signed
int nsi = 0xFEDCBA98; si_left_shift(nsi, 4); si_right_shift(nsi, 4); exit(0); }

編譯 && 執行:

$ gcc -o shift shift.c 
$ ./shift 
12345678 << 4: 23456780
12345678 >> 4: 01234567
FEDCBA98 << 4: EDCBA980
FEDCBA98 >> 4: FFEDCBA9

對於有符號數:

如果數值非負,左移直接丟棄最高位,在低位補對應個數的0;
如果數值非負,右移直接丟棄最低位,在高位補對應個數的0;
如果數值為負,左移直接丟棄最高位,在低位補對應個數的0;
如果數值為負,右移直接丟棄最低位,在高位補對應個數的1

請特別注意,有符號數值右移,高位補的總是原來的符號位值。

(PS:這裡一次性移位4bit,僅為方便觀察結果輸出,若非4的倍數,還需進行計算,想想為什麼?)

無符號左右位移運算
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// unsigned int左移
void ui_left_shift(unsigned int ui, int n)
{
    printf("%08X << %d: %08X\n", ui, 4, ui << n);
}

// unsigned int右移
void ui_right_shift(unsigned int ui, int n)
{
    printf("%08X >> %d: %08X\n", ui, 4, ui >> n);
}

int main()
{
    unsigned int ui1 = 0x12345678;
    ui_left_shift(ui1, 4);
    ui_right_shift(ui1, 4);

    unsigned int ui2 = 0xFEDCBA98;
    ui_left_shift(ui2, 4);
    ui_right_shift(ui2, 4);

    exit(0);
}

編譯 && 執行:

$ gcc -o shift shift.c 
$ ./shift 
12345678 << 4: 23456780
12345678 >> 4: 01234567
FEDCBA98 << 4: EDCBA980
FEDCBA98 >> 4: 0FEDCBA9

對於無符號數:

左移直接丟棄最高位,在低位補對應個數的0;
右移直接丟棄最低位,在高位補對應個數的0,即使最高位原來是1

請特別注意,對於無符號數,不存在正負之分,只有最高位是否為1的區別。

通過對比無符號和有符號數的左右位移結果,我們可知:

1.對於無符號數,不論最高位是否為1,當右移時,高位總是補0;
2.對於有符號數,當右移時,高位總是按位移前最高位值補齊,即,真實的數值符號總是不變的;
3.左移時,不論是否有符號,都丟棄最高位,低位補對應個數的0;