程序員經常把許多獨特但具有相關含義的操作數打包放在一個存儲單元中。
比如:日期和時間的表示,將其打包成一個32位的字。 31 25 24 21 20 16 15 11 10 5 4 0 小型嵌入式系統也會打包數據,以減少可讀寫內存的數量。 如:當某個嵌入式應用程序需要一個布爾值數組時,它就有可能把8個1位的布爾變量打包進每個字節中,而不是使用整個字節來保存一個只能為0或1的值。 BYTE8 flags[8]; 位運算和布爾運算的區別 C語言提供按位運算符和布爾運算符來對位進行操作。但是兩者之間還是有區別的。 布爾運算符用于構成條件表達式(如if 語句中) 按位運算符則用于操縱位 操作 | 布爾運算符 | 按位運算符 | 與 | && | & | 或 | || | | | 異或 | 不支持 | ^ | 非 | ! | ~ |
大多數的C編譯器沒有提供布爾數據類型。作為替代,布爾運算會產生int類型結果,并分別用1和0來表示真值或假植。任何數值數據類型都可以用作布爾操作數。數值0被解釋成假植,任何非0值則解釋成真值。 在編譯器中有如下的定義: Typedef char BOOL; #define FALSE (0) #define TRUE (!FALSE) 按位運算符會把每個操作數視為一個有序的位向量,并產生向量結果。 布爾運算會把每個多位操作數視為單獨一個值,只將它解釋成真值或假植。 如: 布爾: (5||!3)&&6 運算過程如下: (true OR (NOT true ))AND true (true OR false) AND true True AND true 1 按位:(5|~3)&6 運算過程如下 (0000 0101 OR ~0000 0011) AND 0000 0110 (0000 0101 OR 1111 1100) AND 0000 0110 1111 1101 AND 0000 0110 0000 0100 4 常用的對位的操作: 測試位:測試單個位的值。 常用的表達方式有: If((bit&64)!=0)//check to see if bit 6 is set 注意這里的64是十進制的 If((bits&0x0040)) //check to see if bit 6 is set If(bits &(1<<6))//這種代碼比較簡潔 設置、清除和反轉位 設置常用的表達式: Bits =bits | (1<<7);//設置第7位 寫成如下形式更簡潔: Bits |= (1<<7); 清除常用的表達式: Bits &=~(1<<7);//clear bit 7 這里要注意一個數據長度的問題,如果編譯器使用16位的int,而操作數是一個32的int,那么右邊要強制數據類型轉換,寫成 bits &=~(1L<<7); 如果不進行強制轉換,編譯器自動將右邊的數據擴展成32位,以便和右邊的數據兼容,但是編譯器是通過插入0來擴展16-31位的,這樣當涉及到16位或更多的位移動是,就會發生錯誤。如: Printf(“%081x\n”,0xffff ffff L &~(1<<15)); 輸出的結果是0000 7FFF,顯然這不是我們想要的結果。 Printf(“%081X\n”,0xffff ffff &~(1L<<15));輸出的結果是FFFF 7FFF,正確 位的反轉 Bits ^=(1<<6);// flips bit 6 提取位 提取位域的方法是:通過右移以刪除域右邊多余的位,并且與表征碼作“與”運算以刪除左邊多余的位。如:從打包的時間中提取出分鐘 Time 15 11 10 5 4 0 Time>>5 15 11 10 6 5 0 (time>>5)&0x3f 15 11 10 6 5 0 Minutes=(time>>5)&0x3f 提取了6位 15 11 10 6 5 0 插入位:
替換位域的值是通過如下方式完成的:現將其全部清零,然后通過左移位將替換值與位域對齊,在執行“或”運算將其置入打包的操作數中。 注意:如果發生了插入的值超過目標位域的寬度時,那么在將該值插入到打包的操作數中之前,最好先將其與表征碼做“與”運算。 如:將分鐘插入到打包的時間表中
oldtime
15 11 10 5 4 0 Newtime = oldtime & ~(0x3f<<5) 15 11 10 5 4 0 newtime |=(newmins&0x3f)<<5
15 11 10 5 4 0
|