天天看點

C Primer Plus:(第十五章)位操作

按位運算符

基本位運算符:取反~, 與&, 或|, 異或^

  1. 按位取反: ~
unsigned char tmp = 2;
printf("%d", ~tmp);
           

2的二進制是:0000 0010

取反後:1111 1101 解釋成補碼為:(等價于原碼1000 0011 = -3)

  1. 按位與:&
隻有1 & 1 = 1, 其他都為0 , 即:全1為1,有0則0
  1. 按位或:|
隻有0 | 0 = 0, 其他都為1,即:全0為0,有1則1
  1. 按位異或: ^
相同為0, 相異為1

0 ^ 0 = 0,1 ^ 1 = 0

0 ^ 1 = 1, 1 ^ 0 = 1

基本運算符的應用

  1. &

    的應用:掩碼MASK

    不論是0還是1,和0進行與運算為0,和1進行與運算不變:

    是以

    上MASK後,0對應的位被消去,隻有1對應的位保留:類似于用0掩蓋住原二進制串上對應的位:結果是隻有1對應的位被保留,其餘的位為0;
C Primer Plus:(第十五章)位操作
  • 可簡寫為:
  1. 檢查位

    目的:檢查MASK中1對應位是否為1

    先用掩碼(與上MASK),得到第一次處理後的二進制串(其餘不相幹的位置為0),然後==判斷是否與MASK相等:若相等說明MASK中1對應的位也都是1,否則有的位檢查失敗

  1. 關閉位(清空位)

    類似于掩碼:用&将0對應位清空(置為0),一般先将MASK取反,MASK中1的位就是要關閉的位

  1. |

    的應用:打開位(設定位)

無論0還是1,和1進行或運算為1:

是以

上MASK後,可将特定位置為1(ON),用于對特定硬體發送打開指令

  1. ^

    的應用:切換位

    無論0還是1,與0異或不變,與1異或“翻轉”:

    是以

    異或

    上MASK後,可将MASK中1對應的位翻轉

移位運算符: 右移 >>, 左移 <<

  • 左移

    <<

    : 低位補0
  • 右移

    >>

    :無符号數補0,有符号數看機器

移位運算符的應用:

a << n;	// 左移一位相當于*2: 左移n位相當于*2^n
a >> n; // 如果a非負,右移一位相當于/2:右移n位相當于/2^n
           

可以利用移位+掩碼:來提取某個或某些位

應用:ItoB(),invert_end()

獲得int 的二進制:并實作将低n位翻轉的函數

#include <stdio.h>
#include <limits.h>	//提供CHAR_BIT:本機一個位元組的位數(通常為8)
#define MASK 0x01 

void ItoB(int, char*);
void ShowBit(char*);
int invert_end(int, int);

int main(){
	char ans[CHAR_BIT * sizeof(int) + 1];
	int in;
	
	puts("Enter integers and see them in binary.(Non-numeric to quit)");
	while(scanf("%d", &in) == 1){
		ItoB(in, ans);
		printf("%d in binary is ", in);
		ShowBit(ans);
		putchar('\n');
		puts("Inverting the last 4 bits.");
		ItoB(invert_end(in, 4), ans);
		ShowBit(ans);
		putchar('\n');
	}
	
	return 0;
}

void ItoB(int n, char* s){
	int i;
	
	const static int size = CHAR_BIT * sizeof(int);
	for(i = size - 1; i >= 0; --i, n >>= 1){
		s[i] = (n & MASK) + '0';
	}
	s[size] = '\0';
	
	return s;
}
void ShowBit(char* s){
	int i = 0;
	
	while(s[i]){
		putchar(s[i]);
		if(++i % 4 == 0 && s[i]){
			putchar(' ');
		}
	}
}
int invert_end(int n, int bits){
	int mask = 0;
	int bitval = 1;
	
	while(bits-- > 0){
		mask |= bitval;
		bitval <<= 1;
	}
	
	return n ^ mask;
}
           
  • 輸出:
C Primer Plus:(第十五章)位操作
  • 實作翻轉低位功能後:
    C Primer Plus:(第十五章)位操作

位字段:

結構體中的位字段

C11的對齊特性