一、按位异或的概念
按位异或运算符为 ^,它将两个操作数对应的二进制位的每一位一一对应,并进行异或运算。
运算规则:两个对应位相同,结果位为 0;两个对应位不同,结果位为 1。
| 位a | 位b | a ^ b |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
二、按位异或的常见用途
1. 将操作数中的若干指定位翻转
利用异或的特性:
- 某位与 0 异或,结果保持该位原值不变。
- 某位与 1 异或,结果与该位原来的值相反(即翻转)。
因此,如果需要翻转某些位,就将这些位对应的掩码设为 1,需要保持不变的位对应的掩码设为 0,然后与操作数进行按位异或。
示例:将 char 型变量 a 的第 2 位和第 5 位翻转(从 0 开始计数)。
a = a ^ 0x24; // 0x24 = 00100100,第2位和第5位为1,其余为0Code language: JavaScript (javascript)
分析:a 与 0x24 按位异或后,第 2 位和第 5 位被翻转,其余位保持原值不变。
2. 不使用临时变量交换两个变量的值
利用异或运算的性质:a ^ a = 0,a ^ 0 = a,以及异或满足交换律和结合律。
a = a ^ b;
b = a ^ b; // 相当于 b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a
a = a ^ b; // 相当于 a = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = bCode language: JavaScript (javascript)
交换完成后,a 和 b 的值互换。
3. 简单的数据加密
将明文与一个密钥进行异或运算得到密文,再次用相同的密钥与密文异或即可恢复明文。
密文 = 明文 ^ 密钥;
明文 = 密文 ^ 密钥; // 因为 (明文 ^ 密钥) ^ 密钥 = 明文Code language: JavaScript (javascript)
三、代码示例
以下代码演示了按位异或运算的实际应用:
#include <iostream>
using namespace std;
int main()
{
// 示例1:翻转指定位
unsigned char a = 0x5A; // 二进制 01011010
a = a ^ 0x24; // 0x24 = 00100100
cout << "a after flip bits: " << hex << (int)a << endl;
// 01011010 ^ 00100100 = 01111110,十六进制 7e
// 示例2:不使用临时变量交换两个数
int x = 10, y = 20;
cout << "before swap: x = " << x << ", y = " << y << endl;
x = x ^ y;
y = x ^ y;
x = x ^ y;
cout << "after swap: x = " << x << ", y = " << y << endl;
// 示例3:简单加密和解密
char plain = 'A'; // 明文
char key = 0x55; // 密钥
char cipher = plain ^ key; // 加密
char decrypted = cipher ^ key; // 解密
cout << "plain: " << plain << endl;
cout << "cipher: " << hex << (int)cipher << endl;
cout << "decrypted: " << decrypted << endl;
// 示例4:将低4位翻转
unsigned char value = 0xF3; // 11110011
value = value ^ 0x0F; // 0x0F = 00001111
cout << "value after flip low nibble: " << hex << (int)value << endl;
// 11110011 ^ 00001111 = 11111100,十六进制 fc
// 示例5:复合赋值运算符
int flags = 0x12;
flags ^= 0x0F;
cout << "flags after ^= 0x0F: " << hex << flags << endl;
return 0;
}Code language: PHP (php)
四、注意事项
- 按位异或 ^ 不要与幂运算混淆。C++ 中没有幂运算符,幂运算需用 pow 函数。
- 异或运算满足交换律和结合律,且任意数与自身异或结果为 0,与 0 异或结果为其自身。
- 使用异或交换两个变量时,注意不能交换同一个变量,否则会将该变量清零。
- 异或加密非常简单,不适合用于真正的安全加密,仅用于理解异或特性。
五、小结
- 按位异或(^)将两个操作数逐位进行异或运算,相同为 0,不同为 1。
- 主要用途:翻转指定位、不使用临时变量交换两个数、简单加密。
- 翻转操作:目标位与 1 异或,保持不变的位与 0 异或。
- 异或运算具有自反性:a ^ b ^ b = a。