c語言的位操作


c語言的位操作最常用的地方就是用在對寄存器的寫值上。

一.基本的一些概念

  1.位與:&

操作:1 & 1 = 1;  1 & 0 = 0;  0 & 0 = 0;

特點:只有全是1的時候才是1,其他情況都是0.

總結:任何數和0位與就是0,和1位與沒有變化,所以位與常用在清零上(清零用位與)。

  2.位或:|

操作:1 | 1 = 1;  1 | 0 = 1;  0 | 0 = 0;

特點:只有全0的時候才是0,其他情況都是1.

總結:任何數和1位或就是1,和0位或沒有變化,所以位或常用在置1上(置1用位或)。

  3.位取反:~

操作:~1 = 0;  ~0 = 1;

特點:1取反為0,0取反為1.

  4.位異或:^

操作:1 ^ 1 = 0;  1 ^ 0 = 1; 0 ^ 1 = 1; 0 ^ 0 = 0;

特點:相同為0,不同為1.

總結:任何數和1位異或會取反,和0異或沒有變化(特定位要取反就用位異或)。

  5.左移(<<)和右移(>>)

操作的時候要考慮有符號數(signed number)和無符號數(unsigned number)。

對於有符號數:左移的時候右側補0;右移的時候左側補符號位(正數符號位為0,則補0;負數符號位為1,則補1).

對於無符號數:左移的時候右側補0;右移的時候左側也是補0.

注意:我們對寄存器進行賦值的時候用的都是無符號的數

二.與邏輯運算的區別

  1.邏輯運算的基本符號:邏輯與(&&)  邏輯或(||)  邏輯取反(!)

  2.我們需要注意的地方就是:位操作中只有1和0;邏輯操作的中非0代表是真(1),0就代表是假(0)

  3.運算的時候,位運算是把數字拆為一位一位的進行運算的;邏輯運算是把數字作為一個整體進行運算的,但是他們運算的基本操作和位運算一致(譬如:1 && 1 = 1, 0 && 1 = 0 等等)。

    譬如:7 && 0 = 0    111 & 0 = 0

       7 && 3 = 1    111 & 011 = 011 

三.對寄存器寫值的三部曲

  1.首先,把寄存器中的值讀出來

  2.其次,修改寄存器中的值

  3.最后,把修改好的值寫進去

四.代碼實戰

  1、給定一個整型數a,設置a的bit3,保證其他位不變

注意:設置就是設置為1的意思,清除就是清除為0的意思 

1     unsigned int a = 0xc3057ad3;
2     a |= (1<<3);
3     printf("a = 0x%x.\n", a);            //a = 0xc3057adb.

  2、給定一個整形數a,設置a的bit3~bit7,保持其他位不變

1     unsigned int a = 0xc3057ad3;
2     a |= (0x1f<<3);
3     printf("a = 0x%x.\n", a);            //a = 0xc3057afb.

  3、給定一個整型數a,清除a的bit15,保證其他位不變。

1     unsigned int a = 0xc305bad3;
2     a &= ~(1<<15);
3     printf("a = 0x%x.\n", a);            //a = 0xc3053ad3.

  4、給定一個整形數a,清除a的bit15~bit23,保持其他位不變。

1     unsigned int a = 0xc305bad3;
2     a &= ~(0x1ff<<15);
3     printf("a = 0x%x.\n", a);            //a = 0xc3003ad3.

  5、給定一個整形數a,取出a的bit3~bit8。

注意:要取出這個數,首先要把其他位清零&,之后右移就可以得出那個數了

1     unsigned int a = 0xc305bad3;
2     unsigned int tmp;
3     tmp = a & (0x3f<<3);
4     tmp >>= 3;
5     printf("tmp = 0x%x.\n", tmp);

  6、用C語言給一個寄存器的bit7~bit17賦值937(其余位不受影響)。

注意:要賦值就需要把要賦值的那幾位清零&,然后把需要賦值的數左移到那幾位上就可以了

1     unsigned int a = 0xc305bad3;
2     a &= (~(0x7ff<<7));
3     a |= (937<<7);
4     printf("a = 0x%x.\n", a);            //a = 0xc305d4d3.

  7、用C語言將一個寄存器的bit7~bit17中的值加17(其余位不受影響)。

注意:要加值,就要把那幾位的數字取出來,然后把那幾位清零&,之后右移,相加,左移,再置1 |

1     unsigned int a = 0xc305bad3;
2     unsigned int tmp;
3     tmp = a & (0x7ff<<7);
4     a &= (~(0x7ff<<7));
5     tmp >>= 7;
6     tmp += 17;
7     tmp <<= 7;
8     a |= tmp;
9     printf("a = 0x%x.\n", a);            //a = 0xc305c353

  8、用C語言給一個寄存器的bit7~bit17賦值937,同時給bit21~bit25賦值17.

注意:同時賦值和一個個來賦值是一樣的,就是多了幾步而已

    unsigned int a = 0xc305bad3;
    a &= (~(0x7ff<<7));
    a |= (937<<7);
    a &= (~(0x1f<<21));
    a |= (17<<21);
    printf("a = 0x%x.\n", a);            //a = 0xc225d4d3.

不同版本

1     unsigned int a = 0xc305bad3;
2     a &= ((~(0x7ff<<7)) & (~(0x1f<<21)));    
3     a |= ((937<<7) | (17<<21));
4     printf("a = 0x%x.\n", a);            //a = 0xc225d4d3.

五.用宏定義來實現位操作

1.其實目的就是把幾行的代碼寫到一行去(難度也是在這里),我們直接看代碼,自己領悟。

 1 #include <stdio.h>
 2 
 3 //這里就是要把數字x的第n位(bit(n-1)位)置為1
 4 //1U就表示的是無符號的1,宏定義可以傳參的
 5 #define SET_BIT(x,n)    (x | 1U<<(n-1))
 6 
 7 //這里就是要把數字x的第n位(bit(n-1)位)清零
 8 #define CLEAR_BIT(x,n)    (x & ~(1U<<(n-1)))
 9 
10 //這里就是要把數字x的第n到m位置為1(n是低位,m是高位)
11 //就是先把0取反就可以得到很多的1,然后左移就得到那么多個0,再取反就可以得到你想要的1的個數了
12 //最后左移位或就可以置1了
13 #define SET_BITS(x,n,m)    (x | ~(~0U<<(m-n+1))<<(n-1))
14 
15 //截取變量的部分連續位。(就是取出的意思)
16 //其實和上面那里是差不多的,后面那一大部分都是為了確定需要多少個1
17 //最后記得右移,為了得出那個數字
18 #define GET_BIT(x,n,m)    (x & ~(~0U<<(m-n+1))<<(n-1)) >>(n-1)
19 
20 int main (void)
21 {
22     unsigned int a = 0xfffffabf;
23     unsigned int b;
24     
25     b = GET_BIT(a,5,12);                //上面那里就是ab
26     
27     printf("b = 0x%x.\n", b);            //b = 0xab.
28     
29     /*
30     unsigned int a = 0x0;
31     unsigned int b;
32     
33     b = SET_BITS(a,5,8);
34     
35     printf("b = 0x%x.\n", b);            //b = 0xf0.
36     */
37     
38     /*
39     unsigned int a = 0xf;
40     unsigned int b = 0;
41     
42     b = CLEAR_BIT(a,4);
43     
44     printf("b = 0x%x.\n", b);            //b = 0x7.
45     */
46     
47     /*
48     unsigned int a = 0;
49     unsigned int b = 0;
50     
51     b = SET_BIT(a,4);
52     
53     printf("b = 0x%x.\n", b);            //b = 0x8.
54     */
55     
56     return 0;
57 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM