找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3944|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

操作內(nèi)存中的位(詳解)

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

oldtime   
15           11   10             5  4             0
      
時(shí)      
   
      
分         
   
      
     秒/2
   
Newtime = oldtime & ~(0x3f<<5)
15           11   10             5  4            0
      
時(shí)      
   
      
000000      
   
      
    秒/2
   
newtime |=(newmins&0x3f)<<5
15           11   10             5  4            0
      
時(shí)      
   
      
   新的分
   
      
    秒/2
   
                       
     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表