左移和右移運算符:
位移位運算子是右移運算子 (>>),會將整數或列舉型別表達式的位向右移動,而左移運算符會將<<位移到左邊。
1
語法
shift-expression:
additive-expression
shift-expression
<<
additive-expression
shift-expression
>>
additive-expression
備註
這很重要
下列描述和範例適用於 x86 和 x64 架構的 Windows 上有效。 在適用於 ARM 裝置的 Windows 上,左移和右移運算子的實作明顯不同。 如需詳細資訊,請參閱
左移
左移運算子會使中的 shift-expression 位依 所 additive-expression指定的位置數目移轉至左邊。 移位作業已空出的位位置會以零填滿。 左移是邏輯移位(從結尾移出位的位會被捨棄,包括符號位)。 如需位移位類型的詳細資訊,請參閱 位移位。
下列範例顯示使用不帶正負號數位的左移作業。 此範例會藉由將值表示為bitset,來示範位所發生的情況。 如需詳細資訊,請參閱 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 運算子兩端的表達式必須是整數型別。 整數升階會根據 標準轉換中所述的規則執行。 結果的類型與升級 shift-expression的 型別相同。
在下列範例中,類型的 char 變數會升階為 int。
#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)
}
Footnotes
1 以下是 C++11 ISO 規格中班次運算符的描述(INCITS/ISO/IEC 14882-2011[2012]),第 5.8.2 節和 5.8.3 節。
的值 E1 << E2 是 E1 左移位 E2 位置;空置的位會以零填滿。 如果 E1 具有不帶正負號的類型,則結果的值是 E1 × 2E2,減少模數超過結果類型中可表示的最大值。 否則,如果 E1 具有帶正負號的型別和非負值,且 E1 × 2E2 在結果型別的對應不帶正負號類型中表示,則該值會轉換成結果型別,則為結果值;否則,行為是未定義。
的值 E1 >> E2 是 E1 右移位 E2 位置。 如果 E1 具有不帶正負號的型別,或 E1 具有帶正負號的類型和非負值,則結果的值是 E1/2E2 商數的整數部分。 如果 E1 具有帶正負號的型別和負值,則產生的值為實作定義。