2012-03-25 50 views
0

Following my previous question,我需要創建包括設置爲1的位的固體範圍的值I中使用下列的函數:設置一個位範圍中的序

void MaskAddRange(UINT& mask, UINT first, UINT count) 
{ 
    mask |= ((1 << count) - 1) << first; 
} 

然而,如發現,它沒」 t對於count = 32正確工作。的1 << count在這樣的情況下結果理論上是未定義的行爲(或結果),和幾乎在x86是1,因爲換檔操作數處理的模數爲32

欲解決這個表達式爲正常工作這個極端的例子也是。什麼是最簡單/很好/有效的方式來做到這一點?

通過分支(if,?)處理這個特定的情況雖然很醜,但有點簡單,我敢打賭它也是低效的。

另一種方法是將移位操作數提升爲更大類型(64位)。我的意思是:

void MaskAddRange(UINT& mask, UINT first, UINT count) 
{ 
    mask |= (UINT(unsigned __int64(1) << count) - 1) << first; 
} 

有沒有更好的方法?

+0

爲什麼不使用'UINT(-1)'? – 2012-03-25 14:24:33

+0

@Kerrek SB:怎麼樣? – valdo 2012-03-25 14:26:08

+0

嗯。你可以添加一個簡單的,簡短的簡要描述你的函數所需的行爲嗎?我不希望從有問題的代碼中反向設計需求。 – 2012-03-25 14:27:40

回答

1

永遠不要假設任何事情都是無效的,除非你能證明它。在升級到64位時,if-else可能更適合您的架構+操作系統。我認爲除了你已經發布的那兩個以外,還有其他任何理智的方法。

我會去if-else,因爲它文件處理極端情況的意圖。升級到64位並不表示該意圖。

+0

非常感謝您撰寫高效軟件指南的理論文章。但是在我的特殊情況下,我可以很容易地證明分支比單個CPU指令的效率低(已經這樣做)。我也相信,一種理智的方法應該根據「受過教育的猜測」假設一些事實,然後進行強制性驗證。 – valdo 2012-03-25 14:43:47

+0

P.S.我同意使用明確的「if-else」實際上自我記錄了處理特定極端情況的意圖,這有些有價值。更一般地說,OTOH我更喜歡寫一些內在涵蓋所有極端情況的東西(如果可以的話)。然後,更容易看到程序流程,而不需要在思維上考慮所有情況。這通常也會導致更好更通用的表述。 – valdo 2012-03-25 14:53:03

+0

您能否向我們提供您所指的「單CPU指令」?因爲你的(或霍華德)功能永遠不會是單一的指令,我可以保證。但是爲了簡化討論,讓我這麼說:在一個支持64位整數運算的CPU上,你的64位升級代碼將是最有效的。看到你如何使用Windows,你可能運行在一個支持64位整數操作的CPU上。 – Irfy 2012-03-25 15:14:06

0

您可以使用

mask |= (UINT(-1)<<first) & (UINT(-1)>>(32-first-count)) 

這是比較複雜的,但應該在任何情況下工作。這個表達式相對於其他解決方案的效率可能取決於體系結構和編譯器。

+0

有趣。然而,它很容易出現另一種極端情況,其中'first = 0'和'count = 0'。 – valdo 2012-03-25 14:46:36