Cpp 异或运算符详解

异或运算符 ^ 是 C++ 中的位运算符,表示按位异或(XOR)操作。

基本概念

  • 运算符^
  • 运算规则:相同为0,不同为1 0 ^ 0 = 0、 0 ^ 1 = 1、 1 ^ 0 = 1、 1 ^ 1 = 0
  • 操作对象:整数类型(int, char, long等)的二进制位

重要特性

  1. 交换律a ^ b = b ^ a
  2. 结合律(a ^ b) ^ c = a ^ (b ^ c)
  3. 自反性a ^ a = 0
  4. 与0异或a ^ 0 = a
  5. 可逆性:如果 c = a ^ b,则 a = c ^ b

5个应用场景及代码示例

1. 交换两个变量的值(不使用临时变量)

#include <iostream>
using namespace std;

void swapWithXOR(int &a, int &b) {
    a = a ^ b;  // Step 1: a = a ^ b
    b = a ^ b;  // Step 2: b = (a ^ b) ^ b = a
    a = a ^ b;  // Step 3: a = (a ^ b) ^ a = b
}

int main() {
    int x = 5, y = 10;
    cout << "Before: x = " << x << ", y = " << y << endl;
    swapWithXOR(x, y);
    cout << "After: x = " << x << ", y = " << y << endl;
    return 0;
}

2. 查找数组中唯一出现一次的数字

#include <iostream>
#include <vector>
using namespace std;

int findUnique(const vector<int>& nums) {
    int result = 0;
    for (int num : nums) {
        result ^= num;  // 所有出现两次的数字会互相抵消
    }
    return result;
}

int main() {
    vector<int> arr = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    cout << "Unique number: " << findUnique(arr) << endl;  // 输出: 5
    return 0;
}

3. 简单的数据加密/解密

#include <iostream>
#include <string>
using namespace std;

string xorEncryptDecrypt(const string& text, char key) {
    string result = text;
    for (size_t i = 0; i < text.length(); i++) {
        result[i] = text[i] ^ key;  // 加密
        // 对结果再次异或相同的key即可解密
    }
    return result;
}

int main() {
    string message = "Hello, World!";
    char key = 'K';

    string encrypted = xorEncryptDecrypt(message, key);
    cout << "Encrypted (hex): ";
    for (char c : encrypted) {
        printf("%02X ", (unsigned char)c);
    }
    cout << endl;

    string decrypted = xorEncryptDecrypt(encrypted, key);
    cout << "Decrypted: " << decrypted << endl;

    return 0;
}

4. 判断两个数是否符号相反

#include <iostream>
using namespace std;

bool haveOppositeSign(int a, int b) {
    // 利用最高位(符号位)的异或判断
    return (a ^ b) < 0;
}

int main() {
    int x = 10, y = -5, z = 20;

    cout << x << " and " << y << " have opposite sign: " 
         << (haveOppositeSign(x, y) ? "true" : "false") << endl;

    cout << x << " and " << z << " have opposite sign: " 
         << (haveOppositeSign(x, z) ? "true" : "false") << endl;

    return 0;
}

5. 生成校验码或校验和

#include <iostream>
#include <vector>
using namespace std;

char calculateChecksum(const vector<char>& data) {
    char checksum = 0;
    for (char byte : data) {
        checksum ^= byte;  // 异或校验
    }
    return checksum;
}

bool verifyChecksum(const vector<char>& data, char expectedChecksum) {
    char calculated = 0;
    for (char byte : data) {
        calculated ^= byte;
    }
    return calculated == expectedChecksum;
}

int main() {
    vector<char> data = {'A', 'B', 'C', 'D', 'E'};

    char checksum = calculateChecksum(data);
    cout << "Checksum: " << (int)checksum << endl;

    // 模拟传输(假设数据正确)
    cout << "Verification: " 
         << (verifyChecksum(data, checksum) ? "Pass" : "Fail") << endl;

    // 模拟数据错误
    vector<char> corruptedData = {'A', 'F', 'C', 'D', 'E'};  // B变成了F
    cout << "Verification with corrupted data: "
         << (verifyChecksum(corruptedData, checksum) ? "Pass" : "Fail") << endl;

    return 0;
}

额外场景:位操作中的特定用途

// 6. 切换特定位(toggle bit)
unsigned int toggleBit(unsigned int num, int position) {
    return num ^ (1 << position);  // 切换指定位(0变1,1变0)
}

// 7. 判断奇偶性
bool isOdd(int num) {
    return (num ^ 1) != (num + 1);  // 等价于 num & 1
}

int main() {
    unsigned int value = 0b1010;  // 二进制 1010 (十进制10)
    cout << "Original: " << value << endl;

    // 切换第1位(从0开始计数)
    value = toggleBit(value, 1);
    cout << "After toggle bit 1: " << value << endl;  // 变成 1000 (8)

    return 0;
}

注意事项

  1. 优先级问题:异或运算符优先级较低,复杂表达式建议使用括号 cpp int result = (a ^ b) + c; // 明确优先级

  2. 类型限制:只能用于整数类型,不能用于浮点数

  3. 可读性:虽然某些场景下异或很高效,但可能降低代码可读性

  4. 现代编译器优化:对于简单的变量交换,现代编译器能生成更优化的代码,不一定需要手动使用异或

这些应用场景展示了异或在算法、加密、校验和底层系统编程中的实用性,体现了其"相同为0,不同为1"这一简单规则的强大之处。