c及c++的位操作及其對比

來源:互聯網
上載者:User

  首先,我們先瞭解一下相關的概念,我們目前的PC機上面,普遍使用的是32位機,一個整型int為4個位元組,一個char為1個位元組,一個位元組為8位,這裡的位的概念就是今天的主角,在嵌入式領域及系統軟體應用非常廣泛。c/c++是很特殊的進階語言,可以直接操作位,甚至還有位域的概念,可以為一個位元組中的位分別定義概念。使用位,有什麼好處呢,我想應該是可以節約記憶體,效能較高,作為標誌位時,意義非常清晰。在win32 API裡面的標誌位通常就是用這個來完成的,一個位元組就可以用於表示32個標誌了。用上|或者&操作,看起來,多麼完美啊。如我們用於判斷路徑是否為檔案夾:

WIN32_FIND_DATA fileinfo;// File Information StructureHANDLEhFile;// File HandlehFile = FindFirstFile(sDir,&fileinfo);// if the file exists and it is a directoryif(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){//  Directory Exists close fileFindClose(hFile);}else{if(!CreateDirectory(sDir,NULL)){AfxMessageBox("本地建立目錄[" + sDir + "]失敗。");return FALSE;}}

  c的位操作主要包括

操作 運算子 等式及結果 點評
| 0000 0000 | 0000 1001 = 0000 1001 對每一位而言,逢1則為1
並且 & 0010 1111 & 1000 0000 = 0000 0000 對每位計算,逢0則為0,全1才為1
取反 ~ ~1010 0111 = 01011000 這個最好理解,逢1為0,逢0為1
異或 ^ 0000 1001 ^ 1010 1010 = 1010 0111 兩個操作位不同則為1,相同則為0
左移 << 0101 1000 << 2 = 0110 0000 將所有位向左邊移動,並將左邊的移動位拋棄,右邊補0
右移 >> 01100000 >> 4 = 0000 0110 將所有位向右邊移動,右邊移動位拋棄,左邊補0

針對這幾個運算子,我們實驗一把

C的位操作#include <stdlib.h>#include <string.h>#include <assert.h>void print_bit(unsigned char b){/*因無法直接存取位值,只能通過&運算來測試某位是等於或者是*//*當然,現在我們這個辦法是比較蠢的,因為變成你不得不得去計算這幾個十六進位的值,等會再想個好點的辦法*/printf("%c",(b & 0x80)?'1':'0');/*1000 0000*/printf("%c",(b & 0x40)?'1':'0');/*0100 0000*/printf("%c",(b & 0x20)?'1':'0');/*0010 0000*/printf("%c",(b & 0x10)?'1':'0');/*0001 0000*/printf("%c",(b & 0x08)?'1':'0');/*0000 1000*/printf("%c",(b & 0x04)?'1':'0');/*0000 0100*/printf("%c",(b & 0x02)?'1':'0');/*0000 0010*/printf("%c",(b & 0x01)?'1':'0');/*0000 0001*/}int main(){/*00000000*/unsigned char b = 0;printf("初始化時:\n");print_bit(b);printf("\n----------------------------------\n\n");/*設定第,4位為00000000 | 00001001 = 00001001*/print_bit(b);b |= 0x9;printf(" | 00001001 = ");print_bit(b);printf("\n----------------------------------\n\n");/*異或00001001 ^ 10101010 = 10100111*/printf("異或^操作:");print_bit(b);printf(" ^ 10101010=");b ^= 0xAA;print_bit(b);printf("\n----------------------------------\n\n");/*取反~10100111 = 01011000*/printf("取反~操作:~");print_bit(b);printf("=");b = ~b;print_bit(b);printf("\n----------------------------------\n\n");/*左移01011000 << 2 = 01100000*/printf("取左移<<2操作:");print_bit(b);b = b<<2;printf(" <<2 =");print_bit(b);printf("\n----------------------------------\n\n");/*右移位*/printf("右移>>4操作:");print_bit(b);b = b>>4;printf(" >>4 =");print_bit(b);printf("\n----------------------------------\n\n");return 0;}

下面,我們再來看看C++的位操作是怎樣的。C++的位操作,當然是STL的bitset了。

以下表摘自CPPPrimer第二版4.12

操作 功能 用法
test(pos) pos位是否為1? a.test(4)
any() 任意位是否為1? a.any()
none() 是否沒有位為1? a.none()
count() 值是1的位的個數 a.count()
size() 位元素的個數 a.size()
[pos] 訪問pos位 a[4]
flip() 翻轉所有的位 a.flip()
set() 將所有位置設為1 a.set()
set(pos) 將pos位置設為1 a.set(4)
reset() 將所有位置設為0 a.reset()
reset(pos) 將pos位置設為0 a.reset(4)
     

 

針對上面的c程式,我們可以寫出對應的c++版本,這裡也不去寫了,畢竟針對bitset的操作不用像C那樣做麻煩的16進位的計算

總結:

bitset相對於原始C的位操作,相對直觀,代碼清晰,易於理解,不需要程式做機械性的2進位及16進位的換算。對於比較少接觸位操作的
人們而言未嘗不是一種福音,但是對於經常做位操作的嵌入式程式員來講,估計會覺得還是直接用位操作符比較省事。也許這種差別跟Unix的
CLI(命令列模式)及WIN的GUI(視窗介面)一樣,從初步來看滑鼠比較易用,但對於熟練人員而言(比如程式員),往往用命令列更加的高效,且
便於批處理。扯遠了。其實,從辨證的角度是不是可以兩者結合使用呢?像win專註於用戶端,而讓unix專註於伺服器呢?又一次扯遠了!

 

Technorati 標籤: 位操作,bitset,c,c++,對比

 


 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.