C中的XOR运算符

时间:2014-01-10 00:32:57

标签: c bit-manipulation bitwise-operators xor

在进行按位操作时,我无法确定何时使用XOR运算符。 Bitwise And和Or非常直接。如果要屏蔽位,请使用按位AND(常见用例是IP寻址和子网掩码)。当你想打开位时使用包含或。然而,XOR总是让我感觉如果在面试中被问到需要使用XOR的问题,我将永远不会得到它。有人可以说明何时使用它以及一些常见的用例。

5 个答案:

答案 0 :(得分:7)

使用独占或翻转位 - 打开的位置关闭,反之亦然。例如,这对于交换两个数字而没有第三个数字的空间非常方便。

0x0A ^ 0xFF = 0x03 ( 00001010 ^ 11111111 = 11110101 )

交换号码:

operation   example 
             A      B
initial:   0011    1010
a = a^b;   1001    1010
b = a^b;   1001    0011
a = a^b;   1010    0011

如您所见,数字(本例中为半字节)A和B在不使用额外空间的情况下进行了交换。这适用于任何两个相同类型的数字(尽管在C中,按位运算符期望无符号整数)

XOR操作也用于“弱加密”。您可以使用(重复的)“代码字”获取字符串的XOR,结果将是一串没有意义的字节。再次应用相同的操作,出现原件。这是一个相当弱的算法,不应该在现实生活中使用。

关于切换位 - 在“过去的日子”中,如果你想反转一个图像,你会为每个像素做pix = pix & 1 - 或者你可以一次做一个字节,{{1} }。这将把白色背景上的黑色文本变成黑色背景上的白色文本。我认为ATARI通过使用位图进行XOR来获得在屏幕上任何位置创建闪烁光标的专利。

同样,如果你有一个想要创建闪烁灯的微控制器,反复执行byte = byte & 0xFF将导致状态切换。

最后,有许多依赖于XOR操作的“有点笨拙的黑客”。例如,计算字的奇偶校验(即设置位数是奇数还是偶数)可以通过以下方式完成(来源:http://graphics.stanford.edu/~seander/bithacks.html

state = state XOR 1

还有许多其他“聪明的技巧” - 当你试图找到最快的方法来做一些涉及位操作的东西时,它们通常会出现。大多数人都可以完美地度过生活,而没有真正“得到”它,这没关系。我,我喜欢小摆弄。

答案 1 :(得分:2)

我最喜欢的一个例子是就地交换。 (注意:这是C ++代码,而不是C代码,但你明白了。

void swap(int &x, int &y)
{
    x ^= y;
    y ^= x;
    x ^= y;
}

您也可以切换单个位:(n是第n位,在b中切换)

a = b ^ (1 << n)

另一种不太常见的用法:XOR Linked Lists

  • 您可以保持下一个和上一个项目的XOR,而不是保持每个项目的指针。这些天,我们有太多的记忆,可能没关系,但嘿,它仍然很酷。 (除非你是在嵌入式系统上,并且由于某种原因你需要一个双向链表。然后你会很高兴你读到这个。)

答案 2 :(得分:2)

除了交换两个数字和位切换,其他答案解释为逐位XOR也用于查找最多两个数字而不使用if语句

int max(int x, int y)
{
      return x ^ ((x ^ y) & -(x < y)); 
}

答案 3 :(得分:2)

在创作方面,XOR操作通常用于根据给定点的当前X和Y坐标渲染简单的方形图形。例如,棋盘外观类似于可变单元格大小的模式:

#include <stdio.h>

#define CELLSIZE 2   /* cell size is actually 2 power CELLSIZE */
#define MASK (1<<CELLSIZE)

int main()
{
    int i,j;

    for (i=0;i<32;i++)
    {
        for (j=0;j<32;j++)
            putchar (' '+('*'-' ')*( ((i&MASK)^(j&MASK))!=0 ) );
        putchar ('\n');
    }
    return 0;
}

    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
    ****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****
****    ****    ****    ****

在视频游戏编码中,当你没有硬件精灵和/或多个游戏场时,最简单的方法是在位图背景的顶部绘制一个精灵,这样你就可以在方便的时候擦除它而不必存储部分屏幕精灵修改,是对具有背景像素的精灵像素进行异或(一个像素由一位编码)。要擦除精灵,只需在相同的坐标处再次绘制它。也可以看到此方法将鼠标指针呈现在某些非加速显示硬件上。

答案 4 :(得分:0)

特别是当给出除了一个重复的每个数字的数组并且要找到非重复的单个数字时,可以看到XOR的应用。对所有数字进行XOR将导致仅出现一次的数字。

int arr[]={1, 1, 2, 2, 3, 3, 4};
// frequency of every number in the array is 2 except one number.
int sz=7; //size of array
int x=0; 
for(int i=0;i<sz;i++)
   x^=arr[i];
// x would give the number 4 here