2014-03-27 31 views
3

我想弄清楚這個代碼是如何工作的,但我無法設法得到一個單一的答案。在C++中解釋位測試宏

#define testbit(x, y) ((((const char*) & (x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07))) 

我是新的指針,所以如果你能想出一個方法來解釋這個簡體中文,我會很感激。

它屬於對代碼段的X飛機插件在https://code.google.com/p/xplugins/source/browse/trunk/Xsaitekpanels/SwitchPanel.cpp?r=38線發現= 19

+0

爲什麼downvote?因爲它提到了一個宏?這是一個很好的問題。只需將轉換和位掩碼操作分解爲不同的步驟即可。我只是懶惰地回答... –

回答

7

該宏測試x中第y位的值。您不能直接尋址位,所以代碼首先將x視爲一個字節數組(const char*強制轉換)。

然後查找位所在的字節。在一個字節中有8位,所以它被8除。追逐性能,而不是簡單地除以8,代碼使用右移3位的二進制技巧。通常,對於無符號的xy,x >> y = x/2^yx << y = x*2^y

此時您需要測試該字節內的位,因此您可以獲得y/8的其餘部分。還有一點小把戲,用y & 7代替更清晰的y % 8

有了這些信息,您可以製作一個掩碼,一個單獨的位,0x80並將其移位到測試y%8位的位置。面具相與針對字節和這裏非零結果意味着該位被設置爲1,否則爲0

+0

謝謝,節奏的拳頭手。 ,因爲它分開了,它是否移位,將它們轉換成字節的高位,例如,0x06 >> 3等於0xC0還是等於0?或任何其他結果? – Banegas

+1

@ user3466744如果這個答案對你有幫助,你應該接受它:) – yizzlez

+1

C++中沒有旋轉,零從左邊加入,所以0x6 >> 3 = 6/8 = 0在整數數學中。我添加了一些關於轉換技巧的註釋。 –

0

你看到的是一個宏,使下面的工作:

(爲了)

  • 使一個比特移位至y(值:3)
  • 即取x的地址,並選擇在位置y的字符(進入串x)
  • 在所選字符和0x80之間進行二進制操作
  • 將位移移到前一結果(值:7 - (y和0x7之間的二進制運算結果))

那麼,這對你有幫助嗎?我不這麼認爲!

因爲這個宏是不正確的,有點棘手。

位掩碼,二進制運算,二進制移...

如果你能解釋更多precisly要在此明白了什麼,也許我可以是有益的。

+1

好的嘗試,其他人釘了它!對不起...... –

2

完成@ RhythmicFistman的回答

@ RhythmicFistman的回答是缺少一個小的一部分,它和這是輪班的最後一步。

>> (7-((y)&0x07)步驟確保你永遠只能得到1或0的結果有了這個代碼是安全的不喜歡攀比:

if (testbit(varible, 6) == 1) { 
    // do something 
} 

凡未經那一步testbit將返回位掩碼中第6位將被設置爲1或0,並且所有其他位總是被設置爲0.這是意圖,但是它並沒有在被認爲是便攜式方式中實現,參見警告3以下。

使用此代碼

我們添加一些其他的答案可能出現的問題。其他答案還沒有指出應該在這裏提到的一些關鍵字,它們是strict aliasingshift arithmetic right。我的闡述將以下面的警告形式出現。

警告1:Endianness

此代碼假定您使用的是big endian架構或者只想從字符數組得到正確的位。

的原因是,當你轉換的intchar S(字節)的數組,你會得到一個big endian機上不同的結果Vs的little endian機。

警告2:Strict Aliasing

宏利用鑄造(const char*) &(x),其目的是改變類型,也叫做別名的(x),使其更容易得到正確的位。

這是危險的,其原因是在this SO answer精美地解釋。簡短的版本是,如果您通過優化編譯此代碼,可能會發生奇怪的事情。

AliasingPointer Aliasing上的維基百科頁面也很有用,應該閱讀。

警告3:Shift Arithmetic Right

除了這個有可能是與此代碼使用右移操作>>方式的潛在問題。該操作符具有兩種不同的行爲,具體取決於其操作的變量是有符號的還是無符號的。只要你從不使用負數,你就會安全,但是這段代碼不會保護你免受這個錯誤。不過,我懷疑,無論如何你都不太可能犯這樣的錯誤,所以應該可以使用它。

另外值得一提的是,您正在使用signed char,並且正在向右移動。雖然這有效,但我更希望unsigned char這將提高可移植性,因爲當charint是相同的寬度(實際上幾乎從未如此,授予)時,它不會產生算術右移。這是可行的,因爲char提升爲int換班,請參閱this SO answer的解釋。