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.