《C语言进阶》2--位操作

一、位操作符

        1.常用位操作符

        位与&:

        (1)位与符号是一个&,两个&&是逻辑与。

        (2)位与就是两个操作数按照二进制数,每一位进行逻辑与。

         位或|:

        (1)位或是一个|,逻辑或是||。

        (2)位与就是两个操作数按照二进制数,每一位进行逻辑或。

         位取反:

        (1)C语言的位取反~,逻辑取反是!。

        (2)按位取反是将操作数的二进制位逐个按位取反(1变成0,0变成1)﹔而逻辑取反是真(在c语言中只要不是0的任何数都是真)变成假(在c语言中只有O表示假)、假变成真。

         位异或^:

        (1)真值表:1^1 = 0 , 0^0 = 0,1^0=1,0^1=1。

        (2)相等为0,不等为1。

        位于、位或、位异或的特点:

                位于:(任何数,就是就是1或者0)与1位与无变化,与0位与变成0。

                位或:(任何数,就是就是1或者0)与1位或变成1,与0位或无变化。

                位异或:(任何数,就是就是1或者0)与1位异或会取反,与0位异或无变化。

        左移位、右移位

                C语言的移位要取决于数据类型。

                对于无符号数,左移时右侧补0(相当于逻辑移位)

                对于无符号数,右移时左侧补0(相当于逻辑移位)

                对于有符号数,左移时右侧补0(叫算数移位,相当于逻辑移位)

                对于有符号数,右移时左侧补符号位(叫算数移位,正数补0,负数补1)

        嵌入式中研究的移位,以及使用的移位是无符号数。


二、位与、位或、位异或,在操作寄存器时的作用

        1.寄存器操作的要求

(1)ARM是内存与IO统一编址的,ARM中有很多内部外设,SoC中CPU通过像这些内部外           设的寄存器写入一些特定的值来操控这个内部外设,进而操控硬件动作。所以可以                 说:读写寄存器就是操控硬件

(2)寄存器的特点是按位进行规划和使用,但读写确实32位一起进行的

(3)寄存器操作的要求:在设定特定位时不能影响其他位。

(4)读-改-写三部曲。读改写的理念就是,当 想改变寄存器的某些特定位时,不会直接去             写它,而是,先读出原来的值,然后再这个基础上修改特定位,再将修改的值写回寄             存器。效果:在不影响其他位的情况下,修改了自己关心的值。

         2.特定位清零( &)

任何数与1位与不变,与0位与变成0。

         如果希望将一个寄存器的某些为变成0,其他的不变,则构造一个二进制数,要清零的

         位置为0,不变位置为1,把原来的数与构造的数进行位与。

        3.特定位置1( | )

任何数与1位或变为1,与0位或不变。

        如果希望将一个寄存器的某些为变成1,其他的不变,则构造一个二进制数,要置1的

        位置为1,不变位置为0,把原来的数与构造的数进行位或。

        4.特定为取反(^)

任何数与1位异或取反,与0位或不变。

           如果希望将一个寄存器的某些为取反,其他的不变,则构造一个二进制数,要取反的

           位置为1,不变位置为0,把原来的数与构造的数进行位异或。


三、用位运算构建特定二进制数

        1.手动计算        

优势:可以完成工作,难道也不大,操作起来也不是很麻烦。

劣势:依赖工具,不直观。

        2.使用移位获取特定位为1的二进制数

(1)比如需要bit3~bit7为1,其他位置全为0的二进制数。可以这样(0x1f<<3).

(2)更难一点,获取bit3~bit7为1,bit23~bit25为1,其余位为0:((0x1f<<3) | (7<<23))。

        3.结合取反获取特定位为0的二进制数

(1)比如需要bit4~bit10为0,其他位置全为1的二进制数。

         运用方法2,可以((0xf<<0) | (0x1fffff<<11))。

         结合取反,可以~(0x7f<<4)。

        4.总结

(1)如果要的数比较少的数为1,大部分为0,则通过连续的1,左移得到。

(2)如果要的数比较少的数为0,大部分为1,则通构建其反数,然后取反。

(3)如果要的数连续1(连续0)的部分不止一个,这可以分别构造,然后位或。 


 四、位运算练习 

要置1用(|),要清零用&,要取反用^,~和<< >>用来构建特定二进制数。

        (1)给定一个整型数a,设置a的bit3,保证其他位不变。

                a =  a | (1<<3)  或者 a |= (1<<3)

        (2)给定一个整型数,设置bie3~bie7,保证其他位置不变。

               a =  a | (0x1f<<3) 或者a |= (0x1f<<3) 

        (3)给定一个整数a,清楚a的bit15,保证其他位不变。

                a = a & (~(1<<15))  或者 a &= (~(1<<15))

        (4)给定一个整型数a,清楚a的bit15~bit23,保证其他位不变。

                a = a & (~(0x1ff<<15)) 或者a &= (~(0x1ff<<15))

        (5)给定一个整型数a,取出a的bit3~bit8。

                第一步:先将这个数bit3~~bit8不变,其余位全部清零。
                第二步:再将其右移3位得到结果。
                第三步:C语言实现即可。

                a &= (0x3f << 3);

                a >>=3;

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

                第一步,先将bit7~-bit17全部清零,不能影响其他位。

                第二部,位或赋值。

                a &= ~(0x7ff<<7);

                a |= (937 << 7);

        (7)用C语言给一个寄存器的bit7~bit17中的值加17(其余位不受影响)。

                第一步,先读出原来bit7~~bit17的值
                第二步,给这个值加17
                第三步,将bit7~~bit17清零
                第四步,将加数赋值进去

                int temp = a&(0x3ff << 7);

                temp >>=7;

                temp+=17;

                a &= ~(0x3ff<<7);

                a |=(temp<<7);

        (8)用C语言给一个寄存器的bit7~bit17赋值937,同时给bit21~bit25赋值17。

                a &= ~((0x7ff<<7) | (0x1f<<21));

                a |= ((937<<7) | (17<<21));

五、用宏定义来完成位运算

        1.直接用宏来置位、复位(最右边为第一位)

        U的意思时表示无符号数。

        #define SET_NTH_BIT(x , n)         (x |  ((1U) <<(n-1) )

        #deine CLEAR_NTH_BIT(x , n)     (x &~((1U)<<(n-1)) )

       //~0U得到32个1,然后>>32-(m-n+1)得到前面是32-(m-n+1)个0,后面是m-n+1个1,再<<(n-         1),就得到了从第n位到m位为1,其余位为0。

        #define SET_NTH_BIT_m(x , n , m)     (x | ((~0U)>>(32-(m-n+1))<<(n-1))

        2.截取变量的部分连续位

                //   ~的优先级高于<< 、>>

                //~(~(0U)<<(m-n+1))<<(n-1),~(~(0U)<<(m-n+1))可以给低位m-n+1个1,然后在左移到

                n位置。

                #define GETBITS(x , n , m )           ( ( x & ~(~(0U)<<(m-n+1))<<(n-1))>> (n-1) )

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值