C/C++位操作簡介

來源:互聯網
上載者:User

前言


我注意到有些人對位元運算感到困惑,所以我決定寫這篇簡單的教程來說明位元運算如何操作。

位簡介


位,它是什嗎?你可能會問。

簡單來說,位就是1和0,在電腦中做的每一件事都是由它們組成的。電腦中所有的資料使用的是位。一個位元組由8個位組成;一個字由兩個位元組組成,即16個位;而一個雙字由四個位元組組成,即32個位。

 0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0

||              |               |               |              ||

|+- bit 31      |               |               |       bit 0 -+|

|               |               |               |               |

+-- BYTE 3 -----+--- BYTE 2 ----+--- BYTE 1 ----+-- BYTE 0 -----+

|                               |                               |

+----------- WORD 1 ------------+----------- WORD 0 ------------+

|                                                               |

+--------------------------- DWORD -----------------------------+

使用位元組,字或者雙字來進行位操作顯得比較美觀,就像使用一個小型數組或結構。使用位元運算,可以檢查或設定單獨某一位的值或組位的值。

十六進位數和位的關係


人們發現,使用二進位標記表示數字比較的困難。為避免這一問題,採用十六進位計數法(基數為16)。

十六進位的一位元字從0到15分別用二進位的四位來表示。四位一組,即半位元組。一個位元組有兩個半位元組,則可以用兩位十六進位數表示一個位元組的值。

半位元組     十六進位數

======   =========

 0000        0

 0001        1

 0010        2

 0011        3

 0100        4

 0101        5

 0110        6

 0111        7

 1000        8

 1001        9

 1010        A

 1011        B

 1100        C

 1101        D

 1110        E

 1111        F

如果有一個位元組,內容為字母‘r’(ASCII 碼 114),則表示如下:

0111 0010 位元

  7    2  十六進位數
記為:0x72

 

位元運算符

共有6種位元運算符,如下:

  &  與運算子

  |  或運算子

  ^  異或運算子

  ~  取反運算子

 >>  右移運算子

 <<  左移運算子

&  運算子


&(與)運算要求有兩個運算值,然後返回一個值,若且唯若兩個運算值都位1時,傳回值為1。如下表:
   1   &   1   ==   1
   1   &   0   ==   0
   0   &   1   ==   0
   0   &   0   ==   0
  
一個位元組可以包含位標誌,而使用與運算可以通過設定掩碼來檢查某位的值。演算法如下:它用來判斷位元組中的第四位是否為1

BYTE b = 50;

if ( b & 0x10 )

    cout << "Bit four is set" << endl;

else

    cout << "Bit four is clear" << endl;
通過以下計算可以得到結果:

    00110010  - b

  & 00010000  - & 0x10

  ----------

    00010000  - result

所以,第四位為1。

| 運算子


|(或)運算子要求兩個運算值,然後返回一個值,若且唯若兩個運算值中有一個為1或都為1時,傳回值為1。如下表:
   1   |   1   ==   1
   1   |   0   ==   1
   0   |   1   ==   1
   0   |   0   ==   0
  
使用或運算可以保證位元組中的某位為1。演算法如下:它用來保證第二位總是為1

BYTE b = 50;

BYTE c = b | 0x04;

cout << "c = " << c << endl;
通過以下計算可以得到結果:

    00110010  - b

  | 00000100  - | 0x04

  ----------

    00110110  - result

   

   

^ 異或運算子

^ (異或)運算子要求有兩個運算值,然後返回一個值,若且唯若兩個運算值中有一個為1但不同時為1時,傳回值為1。如下表:

   1   ^   1   ==   0

   1   ^   0   ==   1

   0   ^   1   ==   1

   0   ^   0   ==   0

  

使用異或運算可以翻轉特定的位。即0變1,1變0。演算法如下:翻轉第三和第四位
BYTE b = 50;

cout << "b = " << b << endl;

b = b ^ 0x18;

cout << "b = " << b << endl;

b = b ^ 0x18;

cout << "b = " << b << endl;
通過以下計算可以得到結果:

    00110010  - b

  ^ 00011000  - ^ 0x18

  ----------

    00101010  - result

   

    00101010  - b

  ^ 00011000  - ^ 0x18

  ----------

    00110010  - result

   

   

~ 取反運算子

~(取反)運算子只要求一個運算值,然後將所有的1變成0,所有的0變成1。使用取反運算可以將某些位元組置0,確保其它位元組置1,而不用考慮資料的大小。演算法如下:將所有位置1,而第一和第零位置0
BYTE b = ~0x03;

cout << "b = " << b << endl;

WORD w = ~0x03;

cout << "w = " << w << endl;
通過以下計算可以得到結果:

    00000011  - 0x03

    11111100  - ~0x03  b

    0000000000000011  - 0x03

    1111111111111100  - ~0x03  w

   

同&(與)運算子一起使用,可以使任意位置0。演算法如下:將第四位置0
BYTE b = 50;

cout << "b = " << b << endl;

BYTE c = b & ~0x10;

cout << "c = " << c << endl;
通過以下計算可以得到結果:

    00110010  - b

  & 11101111  - ~0x10

  ----------

    00100010  - result

   

   

>>和<< 右移和左移運算子

>>(右移)運算子和<<(左移)運算子將資料右移或左移若干位。>>右移運算從高位往低位移,<<左移運算從低位往高位移。
BYTE b = 12;

cout << "b = " << b << endl;

BYTE c = b << 2;

cout << "c = " << c << endl;

c = b >> 2;

cout << "c = " << c << endl;
通過以下計算可以得到結果:

    00001100  - b

    00110000  - b << 2

    00000011  - b >> 2

   

   

位段

位段是位元運算中比較令人感興趣的部分。使用位段可以在一個位元組,字或雙字內設定小型結構。例如:要記錄日期,要求儘可能少的使用記憶體,則可以採用如下的結構申明:
struct date_struct {

    BYTE day   : 5,   // 1 to 31

         month : 4,   // 1 to 12

         year  : 14;  // 0 to 9999

    } date;

   

在上面的例子中,日佔據了最低的5位,月份佔據了接下來的4位,年份為接下來的14位。則整個日期儲存在三個位元組的23位中。第二十四位被忽略。如果使用整形申明則將佔據12個位元組。
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|

  |                           |       |         |

  +------ year ---------------+ month +-- day --+

 

如上所述,date類型使用的位段結構。這裡使用的是BYTE。一BYTE為8位,使用的時候,編譯器將申請一個BYTE來儲存。如果結構超過8位,編譯器將再申請一個BYTE,直到足夠用來儲存結構。如果使用字或雙字,編譯器將總共申請32位用來儲存結構。

怎樣申明位段?首先申明位段變數,跟著冒號,然後是分配給變數的位元;每位段用逗號分隔,最後用分號表示申明結束。

完成結構申明後,則可以通過存取標記方便的使用結構,同時也可以使用地址操作符使用結構的地址對結構進行操作。如下:

date.day = 12;

dateptr = &date;

dateptr->year = 1852;
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.