c语言的位操作

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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
20int 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
56return0;
57 }。

相关文档
最新文档