左シフトおよび右シフト演算子: <<
および >>
ビット シフト演算子には、整数と列挙型のビットを右に移動する右シフト演算子 (>>
) と、ビットを左に移動する左シフト演算子 (<<
) があります。 1
構文
shift-expression
:
additive-expression
shift-expression
<<
additive-expression
shift-expression
>>
additive-expression
解説
重要
次の説明と例は x86 および x64 アーキテクチャ用 Windows で有効です。 左シフト演算子と右シフト演算子の実装は ARM デバイス用 Windows では大きく異なります。 詳細については、「ARM 入門」ブログ投稿の " シフト演算子 " セクションを参照してください。
左シフト
左シフト演算子では、shift-expression
のビットを、additive-expression
で指定されたビット数だけ左にシフトします。 シフト演算により空いたビット位置はゼロで埋められます。 左シフトは論理シフトです (符号ビットを含めてシフトし、溢れたビットは捨てます)。 ビットごとのシフトの種類の詳細については、「ビットごとのシフト」を参照してください。
次の例では、符号なし数値を使用した左シフト演算を示しています。 値をビットセットとして表すことでビットがどうなるかを示しています。 詳細については、「bitset クラス」を参照してください。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned short short1 = 4;
bitset<16> bitset1{short1}; // the bitset representation of 4
cout << bitset1 << endl; // 0b00000000'00000100
unsigned short short2 = short1 << 1; // 4 left-shifted by 1 = 8
bitset<16> bitset2{short2};
cout << bitset2 << endl; // 0b00000000'00001000
unsigned short short3 = short1 << 2; // 4 left-shifted by 2 = 16
bitset<16> bitset3{short3};
cout << bitset3 << endl; // 0b00000000'00010000
}
符号付き数値をシフトして符号ビットが影響を受ける場合、結果は未定義です。 次の例では、符号ビットの位置まで 1 ビット左にシフトしたときにどうなるかを示しています。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
short short1 = 16384;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b01000000'00000000
short short3 = short1 << 1;
bitset<16> bitset3(short3); // 16384 left-shifted by 1 = -32768
cout << bitset3 << endl; // 0b10000000'00000000
short short4 = short1 << 14;
bitset<16> bitset4(short4); // 4 left-shifted by 14 = 0
cout << bitset4 << endl; // 0b00000000'00000000
}
右シフト
右シフト演算子では、shift-expression
のビット パターンを、additive-expression
で指定されたビット数だけ右にシフトします。 符号なし数値の場合、シフト演算により空いたビット位置はゼロで埋められます。 符号付き数値の場合、その空いたビット位置は符号ビットで埋められます。 つまり、数値が正である場合は 0 を使用し、数値が負である場合は 1 を使用します。
重要
符号付きの負の数値の右シフトの結果は実装に依存します。 Microsoft C++ コンパイラでは空いたビット位置は符号ビットで埋められますが、他の実装でも同様であるとは限りません。
次の例では、符号なし数値を使用した左シフト演算を示しています。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned short short11 = 1024;
bitset<16> bitset11{short11};
cout << bitset11 << endl; // 0b00000100'00000000
unsigned short short12 = short11 >> 1; // 512
bitset<16> bitset12{short12};
cout << bitset12 << endl; // 0b00000010'00000000
unsigned short short13 = short11 >> 10; // 1
bitset<16> bitset13{short13};
cout << bitset13 << endl; // 0b00000000'00000001
unsigned short short14 = short11 >> 11; // 0
bitset<16> bitset14{short14};
cout << bitset14 << endl; // 0b00000000'00000000
}
次の例では、正の符号付き数値を使用した右シフト演算を示しています。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
short short1 = 1024;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b00000100'00000000
short short2 = short1 >> 1; // 512
bitset<16> bitset2(short2);
cout << bitset2 << endl; // 0b00000010'00000000
short short3 = short1 >> 11; // 0
bitset<16> bitset3(short3);
cout << bitset3 << endl; // 0b00000000'00000000
}
次の例では、負の符号付き整数を使用した右シフト演算を示しています。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
short neg1 = -16;
bitset<16> bn1(neg1);
cout << bn1 << endl; // 0b11111111'11110000
short neg2 = neg1 >> 1; // -8
bitset<16> bn2(neg2);
cout << bn2 << endl; // 0b11111111'11111000
short neg3 = neg1 >> 2; // -4
bitset<16> bn3(neg3);
cout << bn3 << endl; // 0b11111111'11111100
short neg4 = neg1 >> 4; // -1
bitset<16> bn4(neg4);
cout << bn4 << endl; // 0b11111111'11111111
short neg5 = neg1 >> 5; // -1
bitset<16> bn5(neg5);
cout << bn5 << endl; // 0b11111111'11111111
}
シフトと昇格
シフト演算子の両側の式は整数型であることが必要です。 整数の上位変換は「標準変換」で説明されている規則に従って実行されます。 結果の型は、昇格した shift-expression
の型と同じになります。
次の例では、int
型の変数が char
に昇格しています。
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
char char1 = 'a';
auto promoted1 = char1 << 1; // 194
cout << typeid(promoted1).name() << endl; // int
auto promoted2 = char1 << 10; // 99328
cout << typeid(promoted2).name() << endl; // int
}
詳細
additive-expression
が負の場合、または additive-expression
が (昇格後の) shift-expression
のビット数以上の場合、シフト演算の結果は未定義です。 additive-expression
が 0 の場合、シフト操作は行われません。
#include <iostream>
#include <bitset>
using namespace std;
int main() {
unsigned int int1 = 4;
bitset<32> b1{int1};
cout << b1 << endl; // 0b00000000'00000000'00000000'00000100
unsigned int int2 = int1 << -3; // C4293: '<<' : shift count negative or too big, undefined behavior
unsigned int int3 = int1 >> -3; // C4293: '>>' : shift count negative or too big, undefined behavior
unsigned int int4 = int1 << 32; // C4293: '<<' : shift count negative or too big, undefined behavior
unsigned int int5 = int1 >> 32; // C4293: '>>' : shift count negative or too big, undefined behavior
unsigned int int6 = int1 << 0;
bitset<32> b6{int6};
cout << b6 << endl; // 0b00000000'00000000'00000000'00000100 (no change)
}
脚注
1 次に示しているのは、C++11 ISO 仕様 (INCITS/ISO/IEC 14882-2011[2012]) の 5.8.2 節と 5.8.3 節でのシフト演算子についての説明です。
E1 << E2
の結果は、E1
を E2
ビット左にシフトした値であり、空いたビットはゼロで埋められる。 E1
が符号なしの型の場合、結果の値は E1 × 2E2、つまり結果の型で表現可能な最大値より 1 大きい数を法とする剰余となります。 E1
が符号付きの型で非負の値であり、E1 × 2E2 が結果の型で表現できる場合、それが結果の値となる。それ以外の場合の動作は未定義である。
E1 >> E2
の結果は、E1
を E2
ビット右にシフトした値である。 E1
が符号なしの型の場合、または E1
が符号付きの型で負ではない値の場合、結果の値は E1/2E2 の値の整数部分となる。 E1
が符号付きの型で値が負の場合、結果として得られる値は実装に依存する。
関連項目
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示