zoukankan      html  css  js  c++  java
  • 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.
    ", a);            //a = 0xc3057adb.

      2、给定一个整形数a,设置a的bit3~bit7,保持其他位不变

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

      3、给定一个整型数a,清除a的bit15,保证其他位不变。

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

      4、给定一个整形数a,清除a的bit15~bit23,保持其他位不变。

    1     unsigned int a = 0xc305bad3;
    2     a &= ~(0x1ff<<15);
    3     printf("a = 0x%x.
    ", 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.
    ", tmp);

      6、用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)。

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

    1     unsigned int a = 0xc305bad3;
    2     a &= (~(0x7ff<<7));
    3     a |= (937<<7);
    4     printf("a = 0x%x.
    ", 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.
    ", 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.
    ", 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.
    ", 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.
    ", 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.
    ", 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.
    ", 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.
    ", b);            //b = 0x8.
    54     */
    55     
    56     return 0;
    57 }
  • 相关阅读:
    vue全局变量定义和修改
    vue格式化显示json数据
    javascript cookie 操作
    bootsrap Collapse用法
    django form 的内置字段类型
    django(channel)到 ubuntu
    django 模型操作
    django 单点登录思路-装饰器
    浏览器右下角提示实现
    django websocket
  • 原文地址:https://www.cnblogs.com/nibuyaoni/p/5547795.html
Copyright © 2011-2022 走看看