C语言位操作-学习笔记

C语言的位操作最常用的地方就是用在对寄存器的写值上。

一 .基本概念

1.位与:&

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

全是1才1,有0则0.

任何数和0位与就是0,和1位与没有变化,所以位与常用在清零上。

2.位或:|

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

全0才0,有1则1.

任何数和1位或就是1,和0位或没有变化,所以位或常用在置位上。

3.位取反:~

操作:~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,保证其他位不变:

unsigned int a = 0x97;    //设定a=10010111;
a |= (1<<3);                            // 对1左移3位=1000,在与a或运算后赋值给a=10011111;
printf(“a = 0x%x.\n”, a); //a = 0x9F.

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

unsigned int a = 0x97;    //设定a=10010111;
a |= (0x1f<<3);                            // 对0x1f左移3位=11111000,在与a或运算后赋值给a=11111111;
printf(“a = 0x%x.\n”, a); //a = 0xFF.

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

unsigned int a = 0x97;    //设定a=10010111;
a &= (1<<5);                            // 对1左移5位=10000,在与a与运算后赋值给a=10000111;
printf(“a = 0x%x.\n”, a); //a = 0x87.

4、给定一个整形数a,取出a的bit2~bit6

unsigned int a = 0x97;    //设定a=10010111;

a &= (0X1F<<2);           // 对0X1F左移2位=1111100,在与a与运算后赋值给a=00010100
a >>=2; //a右移2位,a=101
printf(“a = 0x%x.\n”, a); //a = 0x5.

5、宏定义参数

#define SET_BIT(x,n) (x | 1U<<(n-1))
//这里就是要把数字x的第n位(bit(n-1)位)置为1
//1U就表示的是无符号的1

#define CLEAR_BIT(x,n) (x & ~(1U<<(n-1)))
//这里就是要把数字x的第n位(bit(n-1)位)清零

#define SET_BITS(x,n,m) (x | ~(~0U<<(m-n+1))<<(n-1))
//这里就是要把数字x的第n到m位置为1(n是低位,m是高位)
//就是先把0取反就可以得到很多的1,然后左移就得到那么多个0,再取反就可以得到你想要的1的个数了
//最后左移位或就可以置1了

#define GET_BIT(x,n,m) (x & ~(~0U<<(m-n+1))<<(n-1)) >>(n-1)
//截取变量的部分连续位。(就是取出的意思)
//其实和上面那里是差不多的,后面那一大部分都是为了确定需要多少个1
//最后记得右移,为了得出那个数字

 

参考:https://www.cnblogs.com/nibuyaoni/p/5547795.html