C語言學習筆記——位運算

Lanciberrr發表於2019-11-12

C語言學習筆記

位運算

進位制

  • 程式設計通常使用的是16,10,2進位制
  • 16進位制通常表現為地址形式,數字有:0 1 2 3 4 5 6 7 8 9 A B C D E F,F是10進位制中的15。一般有字首標識,例如0x15A4F,字母的大小寫通常不做區分。
  • 10進位制是我們最熟悉的,可以進行口算,它也是最常用的進位制,數字有0 1 2 3 4 5 6 7 8 9
  • 二進位制是記憶體儲存資料的形式,逢2進1,數字只有0 1
  • 它們之間的轉換有兩種主要演算法:基數相加法和反轉取餘法,但是和我們的思維習慣不一致,我們在實際口算中經常使用的是兩種演算法的結合。

基數相加法

  • 0xAB2轉換為10進位制數
  • 方式:2*16^0 + B*16^1 + A*16^2
  • 0235(8)轉換位10進位制數
  • 方式:5*8^0 + 3*8^1 + 2*8^2
  • 0xAB2轉換位8進位制數
  • 方式:2*20^0 + 13*20^1 + 12*20^2也就是說要把所有的數換成八進位制形式之後,再進行基數相加

反轉取餘法

  • 234轉為8進位制:連續對234除以8,取每次除得的餘數,逆向列印就是結果,其他進位制都用相似的方法就行。
  • 0xAB2轉為8進位制:最好先將AB2轉為10進位制,再進行計算

10、16、2進位制相互轉換

  • 10進位制與16進位制、8進位制:反轉取餘法和基數相加法
  • 2進位制與8進位制、16進位制:一個16進位制位剛好是4個2進位制位數,一個8進位制位剛好是3個2進位制位,因此例如對於1010 0110 1110 0001這樣一個數,轉化為16進位制時,可以直接取每4位,來計算相對應的16進位制位,結果是:A 6 E 1,也就是0xA6E1;轉化為8進位制時:取每3位:001 010 011 011 100 001不夠的前面補0,這樣算得結果是:1 2 3 3 4 1,也就是0123341

操作位的兩種方式:位運算子和位欄位,一個位元組裡面有八位,位的操作就是在這裡面進行的。

按位取反運算子以及整數的儲存

  • 運算子:~,其意義是得到了資料的二進位制的補碼,也就是說(在二進位制內):~1 == 0; ~0 == 1;
  • 整個運算過程都是計算機算的,整數是按照補碼的形式儲存,正數的補碼是本身,負數的補碼是資料位按位取反再加1
  • 注意實型資料不會被支援,這是取決於其儲存方式,編譯器會直接報錯。

按位或、按位與

  • 這兩個運算子分別是:按位或|,按位與&,它們的意義是兩個數進行二進位制的按位比較,公式如下:

      1|1 == 1;
      1|0 == 1;
      0|0 == 0;
    
      1&1 == 1;
      1&0 == 0;
      0&0 == 0;
    
  • 這樣的運算方式與邏輯運算子&&,||極為相似,理解起來比較簡單。

按位異或

  • 運算子:^不同的為1,相同的為0,公式如下:

      1^1 == 0;
      0^0 == 0;
      1^0 == 1;
    
  • 浮點型怎麼使用這樣的運算子?浮點型不能直接使用,會直接報錯,說明它沒什麼意義,如果非要操作,可以使用聯合體:

      union
      {
      	char str[4];//或者直接定義成int型
      	float a;
      }
    
  • 初始化float,然後用str去異或,不過執行結果不太好理解。

  • 聯絡之前的知識:聯合能做的事,強轉也可以做到。*(char*)&a;這樣得到資料之後再去進行操作。

移位運算子

  • 運算子有兩個,位左移<<和位右移>>
  • 正數的左移、右移比較簡單,就是其二進位制形式的所有位向左、右移動多少位,移出去的刪掉,空出來的補0,非常簡單。
  • 對於負數來說,不同的系統結果可能不一樣,左移沒有區別,右移可能會不一樣

位欄位簡介

  • 這個方法的移植性不太好,位運算子完全可以實現位欄位的所有功能,所以說位欄位以瞭解為主。

  • 定義:

      struct Bit
      {
      	int b8:1;
      	int b7:1;
      	int b6:1;
      	int b5:1;
      	int b4:1;
      	int b3:1;
      	int b2:1;
      	int b1:1;
      } B;
    
  • 作用是直接操作具體的某一位,給每一位起個名字。

  • 關鍵字也是struct

  • 注意這裡涉及到了小端儲存,因此第一個成員b8反而是最右側的第一位

  • 成員型別只有三種:(位域)int;unsigned int;_Bool這三種效果一樣,unsigned int用的比較多。

  • 名字:注意冒號,B這個變數有8個位(1位元組)。意思是B8是一個位的名字

  • 通過這樣的,控制每一個位的操作,就可以操作整個資料。
    1

  • 上述程式的結果是41 4(圖中程式的部分沒有寫入)4出現的原因是記憶體對齊。
    2

  • 上述程式的結果是83 4,b8是兩個位,能控制兩個位

  • 如果改變的資料超過其最大限度,系統會警告,而且會當做能改變的最大資料處理。如上述位欄位中如果B.b2 = 3;,系統會報錯並當作B.b2 = 1;處理。

相關文章