C++言語における符号付き整数型の左ビットシフト<<
と符号ビットの関係について。
まとめ:
- 2の補数表現が保証されたC++20現在、左ビットシフト
<<
は論理左シフト(logical left shift)が保証される。 - おまけ:C++20現在、右ビットシフト
>>
は算術右シフト(arithmetic right shift)が保証される。
// 前提:int型==32bit幅 constexpr int x = 1 << 31; // x == -2147483648 (== -2^{31})
C++11時点では符号反転を伴う左ビットシフト演算は未定義動作(undefined behavior)であったがnumeric_limits<T>:::min()
の実装がコア定数式(core constant expression)でなくなるという問題が発覚し、C++14策定段階のCWG DR 1457にて処理系定義(implementation-defined)の振る舞いへと修正された。*1
C++20 7.6.7/p1-3より引用。
1 The shift operators
<<
and>>
group left-to-right.
shift-expression:
additive-expression
shift-expression<<
additive-expression
shift-expression>>
additive-expression
The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.
2 The value ofE1 << E2
is the unique value congruent toE1 × 2E2
modulo 2N, where N is the width of the type of the result. [Note:E1
is left-shiftedE2
bit positions; vacated bits are zero-filled. --end note]
3. The value ofE1 >> E2
isE1/2E2
, rounded down. [Note:E1
is right-shiftedE2
bit positions. Right-shift on signed integral types is an arithmetic right shift, which performs sign-extension. --end note]
関連URL
- c++ - Why was 1 << 31 changed to be implementation-defined in C++14? - Stack Overflow
- c++ - Does C++20 well-define left shift for signed integers that "overflow"? - Stack Overflow
- C++ Standard Core Language Defect Reports, 1457 Undefined behavior in left-shift
- P0907R4 Signed Integers are Two's Complement
- 52119 – [C++11] overflow in signed left shift isn't diagnosed
- cpprefjp: 符号付き整数型が2の補数表現であることを規定