2015-10-21 30 views
7

考慮以下代碼:有符號整型類型按位運算的結果是否定義良好?

using integer = int; // or any other fundamental integral type 
using unsigned_integer = typename std::make_unsigned<integer>::type; 
constexpr integer bits = std::numeric_limits<unsigned_integer>::digits; 
integer value = -42; // or any value 
integer mask = static_cast<integer>(1)<<static_cast<integer>(bits-1); 
bool result_and = value & mask; 
bool result_or = value | mask; 
bool result_xor = value^mask; 

我想知道如何以及是根據標準定義這些操作。我是否有保證在所有架構上獲得相同的結果?我肯定會對所有體系結構上的符號位進行操作,其符號位爲0(正數),1(負數)?

+0

另請參閱[a和b的結果是什麼?](http://stackoverflow.com/q/29394518/1708801),它與密切相關但不重複。 –

回答

3

在標準中,按位和/或按位或按位異或的結果目前未詳細說明,特別是從未定義位。我們有defect report 1857: Additional questions about bits覆蓋這個問題,並說:

的位操作的5.11 [expr.bit.and]規範, 5.12 [expr.xor]和5.13 [expr.or]使用未定義在描述操作時使用術語「按位」,而不指定是否爲 值或視圖中的對象表示。這種分辨率的

某些部分可能被定義的「位」(其否則目前用C未定義++)作爲2.

給定的功率的值和分辨率爲:

CWG決定重新描述操作 本身,以避免引用位,將較大的定義「位」等的問題分割爲考慮進一步考慮的問題1943。

這導致合併defect report 1943: Unspecified meaning of 「bit」

左移符號類型的結果將取決於底層表示。

5.8目前的措辭[expr.shift]第2款使得未定義行爲 創建most-:我們可以從做它明確定義向左轉移到符號位並表示defect report 1457: Undefined behavior in left-shift看到這

:由 左移位(簽字)1到符號位,儘管這不是 罕見完成,正確適用於大多數 (二進制補碼)的架構給定類型的負整數

...如果E1有簽名類型和非負數VA lue,並且E1⨯2E2可以在結果類型中表示,那麼這就是結果值; 否則,行爲是不確定的。

因此,此技術不能用於常量表達式, 將破壞大量的代碼。

地注意到對大多數的 (二進制補碼)架構正常工作的,聲明的重點。所以它依賴於例如二進制補碼的基本表示。

1

關於左和右移位運算符,從C++標準第5.8節:

的行爲是不確定如果將右操作數是負的,或大於 或等於所述長度在受促進的左側的位操作數。

然後它說,向左移位運算符E1 < < E2導致一個未定義的行爲當所有滿足以下條件:

  • 左操作數有符號的類型。
  • 左操作數有一個負值,或者它有一個非負值,使E1×2^E2在結果類型中不可表示。

關於右移運算符E1 >> E2,如果左操作數具有帶符號類型和負值,則行爲與實現有關。

按位AND,XOR和OR運算符對所有積分類型都定義良好。這分別在第5.11,5.12和5.13節中規定。

但是,請注意,有符號整數值的表示可以是二進制補碼,一進制補碼或有符號幅度。儘管大多數編譯器使用二進制補碼錶示法。這些包括gcc,VC++,icl和Clang。

1

運營商&|^是按位,並處理各個位,所以他們會做你寫什麼:應用mask

左移<<操作符有點棘手。如果您改變負值或者將1移至符號位位置或超出位置,它將導致未定義的行爲。

static_cast<integer>(1)<<static_cast<integer>(bits-1);

看來你轉移1那裏籤位的位置,它是不確定的行爲。

相關問題