1. 程式人生 > >位運算子的原理與理解,嘗試通俗總結,歸納普通用法

位運算子的原理與理解,嘗試通俗總結,歸納普通用法

文章目錄

按位運算子

宣告:本部落格口令、通俗理解均為作者個人編造,目的是促進理解與簡單應用,如有不妥忽略即可。

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開始

  1. 第0位 a為1,b為0,根據口令“有0則0,無0則1
    ”,"&"後結果為0
  2. 第1、2位同上原理
  3. 第3位 a為1,b為1,根據口令"有0則0,無0則1","&"後結果為1
  4. 其他位數結果,根據口令,結果均為0
  5. 得到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; 
}

原理:由低位往高位看:

  1. 第0、1位,a為1,b為0,口令“有1則1”,結果均為1
  2. 第6位,a為0,b為0,口令“有1則1,無1則0”,結果為0
  3. 其他位同理,得到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”

  1. 第0位,a為1,b為1,相同,結果為0
  2. 第1位,a為1,b為0,不同,結果為1
  3. 其他位原理同上
  4. 得到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型)