2014-12-10 91 views
4

我相對新的整個位移和C++。如何獲得第n位值

比方說,我有一個uint8_t 00100100(36),我想檢查是否設置了第3位。 這裏是代碼如何即時做到這一點,只有一個位。

uint8_t x = 36; 
    if(x&1<<3) 
     printf("is set"); 

我怎麼可以檢查,如果這是第3 第6位設置?我想檢查幾個比特的組合,如5或7或8。

什麼是最優雅的方式來做到這一點?

+1

可能DUP http://stackoverflow.com/questions/523724/cc-check-if-one-bit-is-set-in-ie-int-variable – 2014-12-10 22:27:11

+1

假設最右邊的位是第一位而不是第零位,只有「<< 2」將第三位移到1的地方。 – 2014-12-10 22:27:35

+1

這些位有沒有具體含義?一個乾淨的方法可能是定義與每個位的語義相關的命名常量。 – SirDarius 2014-12-10 22:30:25

回答

10

通過數字位置檢查位是正確的方法之一,但它使代碼依賴於幻數,這使得它更難以閱讀和維護。

通常,在檢查位掩碼時,有一個檢查某個特定標記的目標,比如說一個硬件寄存器。

想象一下,例如,你的整數的每一位代表你家特定的光,並且要檢查衛生間和廚房是否在:

enum LightMask { 
    ENTRANCE = 0x01, 
    LIVING_ROOM = 0x02, 
    RESTROOM = 0x04, 
    KITCHEN = 0x08, 
    BATHROOM = 0x10, 
    BEDROOM1 = 0x20, 
    BEDROOM2 = 0x40, 
    ATTIC = 0x80 
}; 

uint8_t lightsOn = GetLightsOn(); 

if (lightsOn & (BATHROOM | KITCHEN)) { 
    // ... 
} 

這是優雅的,易於理解和可以很容易地修改。

枚舉也可以在不花錢的編譯器換擋,如果你想明確地使用位的位置,而不是常量的比特來表示:

enum LightMask { 
    ENTRANCE = 1 << 0, 
    LIVING_ROOM = 1 << 1, 
    RESTROOM = 1 << 2, 
    KITCHEN  = 1 << 3, 
    BATHROOM = 1 << 4, 
    BEDROOM1 = 1 << 5, 
    BEDROOM2 = 1 << 6, 
    ATTIC  = 1 << 7 
}; 
+1

雖然用於分配枚舉值的常量bitshift表達式可以增強可讀性,但沒有任何缺點(因爲OP明確要求關於移位)。 – 2014-12-10 22:49:21

+0

@πάνταῥεῖ沒錯,好點。 – SirDarius 2014-12-10 22:49:59

0
uint8_t x = 36; 
if (x & ((1 << 2) | (1 << 5))) 
    printf("is set"); 

,或者如果你知道十六進制:

uint8_t x = 36; 
if (x & 0x24) 
    printf("is set"); 
+1

0x24 = 36.這是從第3位還是第6位得出的? – user1930254 2014-12-10 22:45:16

+1

@ user1930254是,'(1 << 2)| (1 << 5)'相當於'(4)+(32)',它是'36'。 – Julian 2014-12-10 22:47:54

3

如果您不知道哪個位要檢查,直到運行時的位置,一個方法是讓一個函數,所以你可以調用它的任何第n位要檢查:

bool IsBitSet(uint8_t num, int bit) 
{ 
    return 1 == ((num >> bit) & 1); 
} 

uint8_t x = 37; //00100101 
for (int i = 0; i < 8; ++i) 
{ 
    if (IsBitSet(x, i)) 
     printf("%dth bit is set\n", i); 
    else 
     printf("%dth bit not set\n", i); 
} 

輸出將是:

0th bit is set 
1th bit is not set 
2th bit is set 
3th bit is not set 
4th bit is not set 
5th bit is set 
6th bit is not set 
7th bit is not set 

如果我想檢查第3位或6位是否被設置:

uint8_t x = 36; //00100100 
if (IsBitSet(x, 2) || IsBitSet(x, 5)) 
    printf("bit 3 and/or bit 6 is set\n"); 

你也可以將這個功能inline可能提高工作效率。

+1

如果你想要做一個功能,這將是錯誤的方式。最好將它作爲一個宏來實現,以便編譯器可以在編譯時而不是在運行時執行計算。打開函數內聯可以潛在地緩解這個問題,但這樣做沒有任何優勢。 – chacham15 2014-12-10 23:58:50

+0

@ chacham15你說得對。我將這個問題解釋爲OP想要檢查僅在運行時已知的位位置。我正在編輯我的答案以反映這一點。 – DaveS 2017-09-30 07:10:16