位運算子的原理與理解,嘗試通俗總結,歸納普通用法
阿新 • • 發佈:2018-12-16
文章目錄
按位運算子
宣告:本部落格口令、通俗理解均為作者個人編造,目的是促進理解與簡單應用,如有不妥忽略即可。
1.0 按位邏輯運算子
1.1 按位取反(二進位制反碼):~
一元運算子~ 把1變成0,把0變成1
~ (10011010) //表示式
(01100101) //結果值
就簡單理解為得到二進位制反碼就好了
1.2 按位與:&
- 口令:有0則0,(無0則1) //逗號後面可以不記,畢竟不符合前面的0,那麼結果就是1
1.2.1 按位與"&"的原理
示例:
#include <stdio.h>
int main(void)
{
int a=13,b=10;
//a的二進位制為:00001101 (十進位制為13)
//b的二進位制為:00001010 (十進位制為10)
//有0則0
int c = a & b;
//c的二進位制為:00001000 (十進位制為8)
printf("%d",c); //輸出結果為8
return 0;
}
原理:從低位往高位看(低位在右,高位在左)(排位從0開始)
- 第0位 a為1,b為0,根據口令“有0則0,無0則1
- 第1、2位同上原理
- 第3位 a為1,b為1,根據口令"有0則0,無0則1","&"後結果為1
- 其他位數結果,根據口令,結果均為0
- 得到c的二進位制數
1.2.2 按位與"&"的應用:掩碼(Mask)
“掩碼”理解:碼:二進位制數,掩:遮擋,遮掩,掩碼:遮擋住二進位制數的部分位。 Mask:面具。
遮擋原理:用0作遮擋物,遮擋部分全部變成0(使得無法看到原來是1還是0),用1代表無遮擋物,這部分原來是1(0),結果就是1(0)
例項:(原理寫於註釋)
#include <stdio.h>
int main(void)
{
//設定要被遮蓋的碼為:10010110 (十進位制為22或者150)
//我們這裡用有符號的int的22來做示例
int targetCode = 22;
//設定一套mask,想要這個碼中的哪個位表現出來,就在mask中的哪個位設定1
//假設我們只想要把targetCode的第1、2、3位表現出來
//哪位面具mask碼為: 00001110 (十進位制為14)
int mask = 14;
//coveredCode 碼為:0000110 十進位制為6
int coveredCode = mask & targetCode;
//也可以寫成 targetCode &= mask;
//等價於 targetCode = targetCode & mask;
printf("%d",coveredCode); //列印結果為6
return 0;
}
1.3 按位或:|
- 口令:有1則1,(無1則0) //奇奇怪怪的理解方法:按位或"|“就像個"1”,所以1是焦點,有1則1.
- 也可理解:|運算中,任何位與0組合,結果都為本身,與1組合,結果都為1
1.3.1 按位或"|"的原理
示例:
#include <stdio.h>
int main(void)
{
int a =147,b= 60;
//a的二進位制數為: 10010011 (十進位制為147)
//b的二進位制數為: 00111100 (十進位制為60)
int c = a|b;
//c的二進位制數為: 10111111 (十進位制為63)
printf("%d",c); //輸出結果為63
return 0;
}
原理:由低位往高位看:
- 第0、1位,a為1,b為0,口令“有1則1”,結果均為1
- 第6位,a為0,b為0,口令“有1則1,無1則0”,結果為0
- 其他位同理,得到c的二進位制數
1.3.2 按位或"|"的應用:開啟位
理解:控制硬體的時候,需要開啟特定位。我們要知道,開啟對應為1,關閉對應為0。
例項:
#include <stdio.h>
int main(void)
{
//targetCode碼為:00001111(十進位制為15),我們要開啟4、5、7號位
//openTool碼為: 10110000(十進位制為176)
int targetCode = 15;
int openTool = 176;
int openedCode = targetCode | openTool;
//openedCode碼為10111111(十進位制為191)
printf("%d",openedCode); //列印結果為191
return 0;
}
有興趣的朋友可以試試寫個關閉位(按位與、按位或、按位取反的綜合應用)
1.4 按位異或:^
- 口令:“不同為1,相同則0”
1.4.1 按位異或"^"原理
示例:
#include <stdio.h>
int main(void)
{
int a =147 ,b = 61;
//a的二進位制數為: 10010011 (對應十進位制為147)
//b的二進位制數為: 00111101 (十進位制為61)
int c = a ^ b;
//c的二進位制數為: 10101110 (十進位制為174)
printf("%d",c); //列印結果為174
return 0;
}
原理:口令“不同為1,相同則0”
- 第0位,a為1,b為1,相同,結果為0
- 第1位,a為1,b為0,不同,結果為1
- 其他位原理同上
- 得到c的二進位制數
注:在應用異或的時候不需要太在意二進位制的知識
1.4.2(1) 按位異或的兩個應用(一)
int m = a ^ b; //獲得異或表示式,賦值給m,想得到異或表示式的其中一個元素,就需要^除了它本身的其他元素
//例如我們想要得到a,那麼我們就對m異或一個b,得到b同理
int getA = m ^ b;
int getB = m ^ a;
int m = a ^ b ^ c;
//加入我們想要得到a,那麼我們就對m異或一個b和一個c
int getA = m ^ b ^ c;
//一個比較狹隘的應用:假設一個數組中有一堆數字,只有一個數字出現過1次,找出它
#include <stdio.h>
int main(void)
{
int main()
{
int arr[] = {1,2,3,4,1,2,3};
int i = 0;
for(i=1; i<sizeof(arr)/sizeof(arr[0]); i++)
{
arr[0] = arr[0]^arr[i]; //相當於式子:arr[0]=arr[0]^arr[1]^arr[2]...^arr[6]
} //arr[0] = 1^1^2^2^3^3^4
//相同元素異或為0,剩下的結果就是單獨出現的元素
printf("只出現了一次的數是:%d\n",arr[0]);
return 0;
}
printf("%d",m);
1.4.2(2) 按位異或的兩個應用(二)
#include <stdio.h>
int main(void)
{
//輸入19820928顯示students
printf("請輸入19820928:\n");
char ch[8];
ch[0] = 's'^'1';
ch[1] = 't'^'9';
ch[2] = 'u'^'8';
ch[3] = 'd'^'2';
ch[4] = 'e'^'0';
ch[5] = 'n'^'9';
ch[6] = 't'^'2';
ch[7] = 's'^'8';
//注意下面nums元素個數是9個,比輸入的個數多一個,因為要為字串中的\0空字元留個位子
char nums[9];
scanf("%s",nums);
int i;
for(i=0;i<sizeof(nums)-1;i++)
{
printf("%c",nums[i]^ch[i]);
}
printf("\n");
return 0;
}
原理:舉第一個字元為例子:
- 輸入的一個字元(數字),相當於在
ch[0] = 's'^'1';
基礎上又^'1'
(又異或了一個char型1)得到的結果就是’s’本身; - 我們用
's'^'1'
,而不用's'^1
,因為使用者輸入的時候是以char型資料輸入的,所以應該異或的是’1’(char型) 而不是1 (int型)