C++必看:<<左移操作 和 >>右移操作的相关问题

关于<<和>>操作的注意事项

在 C++ 中,<<(左移)和 >>(右移)是 位运算 操作符,用于对整数的二进制位进行移动。它们的补位规则(填充移出的空位)取决于 操作数的类型(是否有符号)和具体的实现(部分情况由编译器决定)。以下是详细分析:


1. 左移操作 <<

规则:低位补 0

  • 无论操作数是 有符号(signed 还是 无符号(unsigned,左移操作 << 都会在 右侧(低位)补 0
  • 左移 n 位相当于乘以 (2^n)(如果未溢出)。

示例

unsigned int a = 0b1101; // 13
a = a << 2;              // 0b110100 → 52 (13 * 4)

  • 0b1101 左移 2 位 → 0b110100(右侧补 0)。

注意事项

  • 如果左移导致 符号位被修改(对于 signed 类型),结果是 未定义行为(UB)

    int b = 0x40000000; // 2^30
    b = b << 2;         // UB! 可能变成负数或溢出
    
    

2. 右移操作 >>

右移的补位规则取决于 操作数是否有符号

(1) 无符号数(unsigned):高位补 0

  • 逻辑右移(Logical Right Shift),高位直接补 0。
  • 右移 n 位相当于除以 (2^n)(向下取整)。

示例

unsigned int c = 0b1101; // 13
c = c >> 2;              // 0b0011 → 3 (13 / 4)

  • 0b1101 右移 2 位 → 0b0011(左侧补 0)。

(2) 有符号数(signed):高位补符号位(算术右移)

  • 算术右移(Arithmetic Right Shift),高位补 符号位的值(正数补 0,负数补 1)。
  • 右移 n 位相当于 带符号的除法(向负无穷取整)。

示例(正数)

int d = 0b1101; // 13 (假设 int 是 4 位)
d = d >> 2;     // 0b0011 → 3 (13 / 4)

  • 0b1101(13)右移 2 位 → 0b0011(3)。

示例(负数)

int e = -8;     // 0b11111000 (假设 8-bit)
e = e >> 2;     // 0b11111110 → -2 (-8 / 4)

  • 0b11111000(-8)右移 2 位 → 0b11111110(-2),高位补 1。

3. 关键总结

操作无符号数(unsigned有符号数(signed
<<低位补 0低位补 0(但符号位被修改时是 UB
>>高位补 0(逻辑右移)高位补符号位(算术右移)

注意事项

  1. 有符号数的左移可能 UB:如果左移后符号位被改变(如 1 << 31),行为未定义。
  2. 右移负数的结果依赖实现:C++ 标准规定 signed >>算术右移,但早期某些机器可能采用逻辑右移(现代编译器基本都遵循算术右移)。
  3. 避免对负数进行位运算:除非明确需要,否则建议使用 unsigned 进行位操作。

代码示例

#include <iostream>
using namespace std;

int main() {
    // 左移(补 0)
    unsigned int u1 = 0b1101; // 13
    u1 = u1 << 2;             // 0b110100 → 52
    cout << u1 << endl;       // 52

    // 无符号右移(补 0)
    unsigned int u2 = 0b1101; // 13
    u2 = u2 >> 2;             // 0b0011 → 3
    cout << u2 << endl;       // 3

    // 有符号右移(补符号位)
    int s1 = -8;              // 0b11111000 (假设 8-bit)
    s1 = s1 >> 2;             // 0b11111110 → -2
    cout << s1 << endl;       // -2

    return 0;
}


4. 如何强制逻辑右移?

如果需要对 signed 数进行逻辑右移(高位补 0),可以 先转换为 unsigned

int x = -8;
unsigned int y = (unsigned int)x >> 2; // 逻辑右移


5. 总结

  • << 总是补 0(但有符号左移可能 UB)。
  • >>
    • unsigned补 0(逻辑右移)。
    • signed补符号位(算术右移)。
  • 建议:位运算尽量用 unsigned,避免未定义行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值