按位异或

一、按位异或的概念

按位异或运算符为 ^,它将两个操作数对应的二进制位的每一位一一对应,并进行异或运算。

运算规则:两个对应位相同,结果位为 0;两个对应位不同,结果位为 1。

位a位ba ^ b
000
011
101
110

二、按位异或的常见用途

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。
Previous:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注