我在識別何時使用XOR運算符進行按位操作時遇到了一些麻煩。按位和和或者非常簡單。如果要屏蔽位,請使用按位AND(常見用例是IP Addressing和子網掩碼)。當你想打開使用包容性或。然而,異或總是讓我感覺好像在面試中被問到一個需要使用XOR的問題時,我永遠不會得到它。有人可以說明何時使用它以及一些常見用例。XOR運算符C
XOR運算符C
回答
您可以使用專用或翻轉位 - ON的位被關閉,反之亦然。例如,這可以方便地交換兩個數字,而不用第三個數字的空間。
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操作也用於「弱加密」。你可以用一個(重複的)「代碼字」取一個字符串的異或,結果將是一串沒有意義的字節。再次應用相同的操作,然後出現原稿。這是一個相當薄弱的算法,不應該在現實生活中使用。
關於切換位 - 在「過去的日子」裏,如果你想反轉一個圖像,你會爲每個像素做pix = pix & 1
- 或者如果你一次可以做一個字節byte = byte & 0xFF
。這會將白色背景上的黑色文字變成黑色背景上的白色文字。我認爲ATARI擁有一項專利,通過與位圖進行異或來在屏幕上的任何位置創建一個閃爍的光標。
類似地,如果您有一個想要創建閃爍燈光的微控制器,重複執行state = state XOR 1
將導致狀態切換。
最後,有很多依賴XOR操作的「搗蛋黑客」。例如,計算一個字的奇偶性(即組的位的數目是奇數還是偶數)可以用下面的(來源:http://graphics.stanford.edu/~seander/bithacks.html)完成
unsigned int v; // word value to compute the parity of
v ^= v >> 16;
v ^= v >> 8;
v ^= v >> 4;
v &= 0xf;
return (0x6996 >> v) & 1;
還有許多其他的「聰明的技巧」 - 它們通常會在您嘗試找到執行涉及位操作的最快方法時顯示出來。大多數人可以完美無缺地完成生活,而不需要真正「獲得」它,這沒關係。我,我喜歡擺弄。
我最喜歡的例子之一是就地交換。 (注:這是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的holdi每個指針指向一個指針。這些日子裏,我們有太多的記憶,可能無所謂,但嘿,它仍然很酷。除了兩個數字,位撥動交換的(除非你是在嵌入式系統上,你需要爲某種原因雙向鏈表。然後你會很高興你讀這一點。)
使用按位異或交換兩個數字是聰明的 - 在這種情況下,這是一件壞事。首先,如果'x'和'y'指向同一個對象,它就會失敗。只需使用一個臨時的。如果被交換的對象非常大,並且您不能分配臨時對象,則一次使用循環交換一個字節或單詞。 –
至於xor鏈接列表技巧,這同樣*聰明*。當你遍歷它時,它會使列表處於不一致的狀態,對指針的這種位操作嚴格地說是未定義的行爲(儘管你可能會在* most *系統上避開它)。 –
'x'和'y'不能指向同一個對象,它們都是整數。除非你把它叫做swap(x,x)',它什麼也不做。 :) – Keeler
在創意方面,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;
}
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
**** **** **** ****
在視頻遊戲編碼,當你沒有硬件精靈和/或多個playfields,最簡單的方法來繪製一個精靈在頂部一個位圖背景,所以你可以在你方便的時候擦除它,而不必存儲精靈脩改的屏幕部分,就是用背景像素對精靈像素進行異或(一個像素由一位編碼)。要刪除精靈,只需在同一座標處再次繪製即可。也可以看到這種方法在一些非加速顯示硬件上渲染鼠標指針。
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
- 1. C++運算符 ''
- 2. 運算符[] [] C++
- 3. 使用x-path「|」運算符
- 4. C++:運算符重載,運算符+
- 5. 一元運算符的區別(+ =,= +,++ x,x ++)
- 6. C++ typeid運算符
- 7. C#Lambda運算符
- 8. C#coalesce運算符
- 9. C++ overload []運算符
- 10. 運算符[&]在C++
- 11. 點運算符C++
- 12. C++ typeof運算符
- 13. 運算符()在C++
- 14. XOR運算符C++
- 15. C++運算符 - >
- 16. C++ delete []運算符
- 17. :c/C++中的運算符
- 18. 字符串運算符C++
- 19. 定時運算符+,運算符,運算符*和運算符/
- 20. C++運算符()括號 - 運算符類型()與類型運算符()
- 21. 調用&(x,y)按位運算符
- 22. X宏生成雜散運算符
- 23. C#如何檢查列表中的n個x(mod運算符?)
- 24. C++ template class overload []運算符
- 25. 運算符=不明確(C++)
- 26. C++運算符優先級
- 27. C++下標運算符
- 28. 困惑?運算符在c#
- 29. 運算符重載C++
- 30. C++ biginteger類運算符=
是的,異或與零無關,結果位不變。與1異或會總是切換該位。 – Graeme
是啊我想,我覺得我永遠不會意識到何時使用它。 – AyBayBay
@AyBayBay如果您獲得更多的經驗並從事更廣泛的問題,您會有所收穫。這是一個相當罕見的操作,所以不要擔心,如果你沒有遇到它的需要。 –