-
C语言位操作,在写嵌入式代码的时候,经常会用到C语言位操作,比如&=,|=,逻辑左移,逻辑右移,算术左移,算术右移
-
位与和逻辑与
位与就直接按照数字电路的知识进行相与就可以了。
这里需要注意的是逻辑与,一个数字,只要他不是等于0 ,那他就表示逻辑1,逻辑与用&&来表示。
比如:5和2进行逻辑与,最后的结果是1。 -
位或,位取反,位异或,这里就不在详述了,因为各位都学过数字电子技术,如果没有学过的,请记得查看数字电路的课本
-
我们这里要重点回顾左移位和右移位的应用
比如将6化为二进制,0000 0110,左移三位,如图
我们可以看到每进行一次左移操作,得到的结果是原来操作数的一倍,进行的是乘法操作,也就是X<<n=X*2^n
现在我们一起来看一下右移位,比如
对8进行右移位3位:
我们可以看到右移位是将原操作数越移越小,进行的是除法操作,并且每进行一次右移,得到的结果是原来操作数的一半
(x>>n=x/2^n) -
在嵌入式开发中,经常会用到寄存器清零或者寄存器置一,我们可以用&和|来完成。
寄存器特定位清零用&=,比如我们要让0x4000FF00中的bit8~bit15清零,我们可以让0x4000FF00与0xFFFF00FF进行位与,得到的结果是0x400000000,所以我们通过读改写的方法,就可以完成寄存器特定位清零的效果
寄存器特定位置一用|=,比如我们要让0x4000FF00的bit0~bit7置一,我们就用0x000000FF与原来的操作数相位或,这样得到的结果就是0x4000FFFF
综上,运行&= 可以对寄存器的特定位进行清零操作,运用|=可以对寄存器的特定位进行置一操作,
6,上面我们说到运用&=和|=对寄存器可以分别进行置零和置一操作,但是每次都要去构造这样的数字就显得很麻烦,有没有更加简单方便的办法呢,有,那就是运用位运算来构建特定的二进制数字,
1)运用移位操作来获取特定位为一的二进制数,比如我们要构造0x4000FF00的
7,利用移位操作,对特定位进行置一操作,比如,对bit2-bit7置一并且对bit25~bit27置一,先对bit2-bit7置一,这个数就是0x3F<<2;再对bit25-bit27置一,这个数就是0x03<<25,集成到一起,就成了(0x3F<<2)|(0x03<<25)
用程序表示:
#include <stdio.h>
int main(void)
{
int a=(0x1f<<3)|(0x07<<23);
printf("%x",a);
return 0;
}
结果如下:
可以看出这种方法很简便
8,结合位取反获取特定位为0的二进制数
比如要设置bit5-bit8为0,其余位均为1的数,我们可以想到bit3-bit4为1,并且bit9-bit32也全部为1 ,也就是 (0xffffff<<9)|(0x1f<<0);
用代码操作如下:
#include <stdio.h>
int main(void)
{
int a=(0xffffff<<9)|(0x1f<<0);
printf("%x",a);
return 0;
}
结果如下:
这样可以完成特定位的置零,但是我们发现这样的方法并不方便,所以特定位(比较少)置零而大部分为1的数,并不适合用很多歌连续1左移的方式来构造,而适合左移加取反的方法来完成,
思路:先尝试构造这个数的反码,然后取反得到这个数。比如要设置bit5-bit8为0,其余位均为1的数,可以构造bit5-bit8为1的数,然后再对这个数按位取反就可以了。
因此代码如下:
#include <stdio.h>
int main(void)
{
int a = (0xF << 5);
printf("%x", ~a);
return 0;
}
可以看出,结果都是一样的,但是第二种方法简便得多!
9,总结:
1)如果你要构造的这个数较少位为1,其余为都为0的话,可以用对1进行连续左移就可以了
2)如果你要构造的这个数较少位为0,大部分为1,可以构造这个数的反码,然后通过取反来求得这个数!