按位运算符与移位运算符

一、基本位运算符

1. 按位与(&

  • 规则:两位都为1时结果为1,否则为0。

  • 用途:提取特定位、掩码操作。

  • 示例

unsigned char a = 0b1010; // 10
unsigned char b = 0b1100; // 12
unsigned char c = a & b;  // 0b1000 → 8

2. 按位或(|

  • 规则:两位中有一个为1则结果为1。

  • 用途:设置特定位。

  • 示例

unsigned char a = 0b1010; // 10
unsigned char b = 0b1100; // 12
unsigned char c = a | b;  // 0b1110 → 14

3. 按位异或(^

  • 规则:两位不同时结果为1,否则为0。

  • 用途:切换特定位、交换变量。

  • 示例

unsigned char a = 0b1010; // 10
unsigned char b = 0b1100; // 12
unsigned char c = a ^ b;  // 0b0110 → 6

4. 按位取反(~

  • 规则:每一位取反(0变1,1变0)。

  • 用途:反转所有位。

  • 示例

unsigned char a = 0b1010; // 10
unsigned char c = ~a;     // 0b0101 → 5(实际为255-10=245,但需注意类型宽度)

二、移位运算符

1. 左移(<<

  • 规则:将二进制位向左移动指定位数,右侧补0。

  • 用途:快速乘以2的幂。

  • 示例

unsigned char a = 0b00001010; // 10
unsigned char c = a << 2;     // 0b00101000 → 40(10*2²=40)

2. 右移(>>

  • 规则

    • 无符号数(unsigned:左侧补0。

    • 有符号数(signed:左侧补符号位(称为算术右移)。

  • 用途:快速除以2的幂(仅对无符号数安全)。

  • 示例

unsigned char a = 0b10100000; // 160
char b = -8;                  // 二进制补码:11111000
unsigned char c = a >> 2;     // 0b00101000 → 40(160/2²=40)
char d = b >> 2;              // 11111110 → -2(保留符号位)

三、关键概念:无符号数 vs. 有符号数

  • 无符号数(unsigned:所有位都表示数值(范围:0 ~ 2ⁿ-1)。

  • 有符号数(signed:最高位为符号位(0正1负),范围:-2ⁿ⁻¹ ~ 2ⁿ⁻¹-1。

  • 移位时的区别

    • 右移无符号数:逻辑右移(左侧补0)。

    • 右移有符号数:算术右移(左侧补符号位)。

四、常见应用场景

  • 掩码操作(提取或设置特定位):
// 提取低4位
unsigned char data = 0xAB; // 1010 1011
unsigned char low = data & 0x0F; // 0x0B (0000 1011)
  • 位标志管理(如权限控制):
#define READ   0b00000001
#define WRITE  0b00000010
#define EXECUTE 0b00000100

unsigned char perm = READ | WRITE; // 设置读写权限
if (perm & READ) { ... }           // 检查读权限
  • 快速乘除(仅限2的幂):
int a = 10;
int b = a << 3; // 10 * 8 = 80
int c = a >> 1; // 10 / 2 = 5
  • 交换变量(无需临时变量):
int x = 5, y = 3;
x ^= y; // x = 5 ^ 3
y ^= x; // y = 3 ^ (5 ^ 3) = 5
x ^= y; // x = (5 ^ 3) ^ 5 = 3

五、注意事项

  1. 移位溢出

    • 左移超过类型位数是未定义行为(如 int32_t a = 1; a << 32)。

  2. 负数右移

    • 对有符号数右移可能导致符号扩展(如 -8 >> 1 得到 -4)。

  3. 优先级问题

    • 位运算符优先级低于算术运算符,建议用括号明确优先级:

int a = 5 & 3 + 2;   // 等价于 5 & (3 + 2) → 5 & 5 = 5
int b = (5 & 3) + 2; // (1) + 2 = 3

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值