C++:左移和右移运算符 (> > 和 < <)

本文介绍了C++中的左移(<<)和右移(>>)运算符,详细阐述了它们的语法、注意事项、左移和右移的原理,以及移位和提升的概念。对于有符号和无符号数字,左移和右移的处理方式有所不同,特别是负数右移的结果依赖于具体实现。文章还强调了当移位表达式超出范围时,结果是不确定的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

按位移位运算符是右移位运算符 (>>) ,它将 shift 表达式 的位移动到右侧,左移运算符 (<<) ,这将向左移动 移位表达式 的位数。

语法

移位表达式 <<加法表达式
shift-expression >> additive-expression

备注

重要
以下说明和示例在 Windows 上适用于 x86 和 x64 体系结构。 对于 ARM 设备,左移运算符和右移位运算符的实现在很大程度上是不同的。

左移

左移运算符使 shift 表达式 中的位向左移动由 加法表达式 指定的位置数。 因移位运算而空出的位上将用零填充。 左移是逻辑移动(从末端移掉的位将被舍弃,包括符号位)

以下示例将显示使用无符号数字的左移运算。 该示例通过将值表示为 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
}

右移

右移运算符使 移位表达式 中的位模式向右移位(由 加法表达式 指定的位置数)。 对于无符号数字,因移位运算而空出的位上将用零填充。 对于有符号数字,符号位用于填充空出的位。 也就是说,如果数字为正,则使用 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
}

移位和提升

移位运算符两侧的表达式必须是整数类型。 根据 标准转换中所述的规则执行整型提升。 结果的类型与提升的 移位表达式 的类型相同。

在下面的示例中,类型的变量 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
}

其他详细信息

如果 加法表达式 为负,或者如果 加法表达式 大于或等于 (提升) 移位表达式 中的位数,则移位运算的结果是不确定的。 如果 加法表达式 为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,减少的模数比结果类型中可表示的最大值多一个。 否则,如果 E1 具有有符号的类型和非负值,并且 E1 × 2E2 可在结果类型的相应无符号类型中表示,则该值转换为结果类型就是生成的值; 否则,该行为是不确定的。

E1 >> E2 的值是 E1 向右移动 E2 位的结果。 如果 E1 具有无符号类型或 E1 具有有符号类型和非负值,则结果的值为 E1/2E2的商的整数部分。 如果 E1 属于有符号类型且为负值,则结果值由实现决定。

该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处,本文章博客地址:https://blog.youkuaiyun.com/it_cplusplus/article/details/118833857

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值