C语言位操作复习

来源:互联网 发布:淘宝买零食有毒吗 编辑:程序博客网 时间:2024/06/07 20:04
一.对c语言位操作的复习 2017/11/19 16:50
a&b:相同为1则为1,否则为0 //特定位清零用&
比如:
举例:假设原来32位寄存器中的值为:0xAAAAAAAA,我们希望将bit8~bit15清零而其他位不变,
可以将这个数与0xFFFF00FF进行位与即可。a=0xAAAAAAAA, b=0xFFFF00FF, c=a&b;
a|b :有1则为1,否则为0//特定位置1用 |
a^b: 有1则为1,否则为0//特定位取反用^
常用位运算:与、或、非、移位
位与(&) 位或(|) 位非(取反 ~) 移位(左移<< 右移>>)
使用位运算实现功能
1<<3 等于 0b1000,即bit3为1
1<<5 等于 0b100000,即bit5为1
(1<<3)|(1<<5) 等于 0b101000
扩展一下:如何只熄灭中间1颗而点亮旁边2颗
ldr r0, =((0<<3) | (1<<4) | (0<<5))
总结:要置1用|,清零用&,要取反用^,~和<< >>用来构建特定二进制数
(1)如果你要的这个数比较少位为1,大部分位为0,则可通过连续很多个1左移n位得到。
(2)如果你想要的数是比较少位为0,大部分位为1,则可通过先构建其位反数,然后再位取反来得到。举例说明:
1.给定一个整型数a,设置a的bit3,保证其他位不变。设置即为1,清除即为0
a=a|(1<<3)
2.给定一个整形数a,设置a的bit3~bit7,保持其他位不变。
a=a|(0b11111<<3) ==a |= (0x1f<<3)//左移3位说明从bit3开始,0x1f表示有连续5位置1
3.保证bit15这个数不变,其余位全部清零。
a=a&((1<<15))
4.给定一个整型数a,清除a的bit15,保证其他位不变。
a=a&(~(1<<15))//左移15位说明从bit15开始,0x1表示有连续1位置0.
5.给定一个整形数a,清除a的bit15~bit23,保持其他位不变。
a=a&(~(0b111111111<<15))==a=a&(~(0x1ff<<15))
//左移15位说明从bit15开始,0x1ff示有这部分有9位

如下实例:
6、给定一个整形数a,取出a的bit3~bit8。
思路:
第一步:先将这个数bit3~bit8不变,其余位全部清零。
a &= (0x3f<<3);
第二步,再将其右移3位得到结果。
a >>= 3;

7、用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)。
关键点:第一,不能影响其他位;第二,你并不知道原来bit7~bit17中装的值。
思路:第一步,先将bit7~bit17全部清零,当然不能影响其他位
a &= ~(0x7ff<<7);
第二步,再将937写入bit7~bit17即可,当然不能影响其他位。
a |= (937<<7);
8、用C语言将一个寄存器的bit7~bit17中的值加17(其余位不受影响)。
关键点:不知道原来的值是多少
思路:第一步,先读出原来bit7~bit17的值
第二步,给这个值加17
第三步,将bit7~bit17清零
第四步,将第二步算出来的值写入bit7~bit17
/*
unsigned int a = 0xc30288f8; // 0xc34648f8
//第一步,先读出原来bit7~bit17的值,
即bit7~bit17不变,将其他位全部清零,然后右移对应的起始bit位
unsigned int tmp = 0;
tmp = a & (0x7ff<<7);
//printf("befor shift, tmp = 0x%x.\n", tmp);
tmp >>= 7;
//printf("after shift, tmp = 0x%x.\n", tmp);
//第二步,给这个值加17,
tmp += 17;
//第三步,将a的bit7~bit17清零
a &= ~(0x7ff<<7);
//第四步,将第二步算出来的值写入bit7~bit17
a |= tmp<<7;
printf("a = 0x%x.\n", a);
*/
9、用C语言给一个寄存器的bit7~bit17赋值937,同时给bit21~bit25赋值17.
思路:4.2.4.6的升级版,两倍的4.2.4.6中的代码即可解决。
/*// 直接double第7题
unsigned int a = 0xc30288f8;
a &= ~((0x3ff<<7) | (0x1f<<21)); // bit7~bit17和bit21~bit25全清零
a |= ((937<<7) | (17<<21)); // 937和17全部赋值

printf("a = 0x%x.\n", a); // 0xc223d4f8
*/
位操作复习main.c:
#include <stdio.h>int main(int argc,char *argv[])//位操作复习{        //6.给定一个整形数a,取出a的bit3~bit8。    unsigned int a =  0xc30288f8;    //第一步,先将a的bit3~bit8不变,其他位全部清零    a&=(0b111111<<3);    //第二步,再将其右移3位得到结果    a>>=3;    printf("after shift, a = 0x%x.\n", a);    /*    //7.用C语言给一个寄存器的bit7~bit17赋值937(其余位不受影响)。      unsigned int a =  0xc30288f8;    a&=~(0b11111111111<<7);//第一步,先将bit7~bit17全部清零,其他位不变    a|=(937<<7);//第二步,再将937写入bit7~bit17即可,当然不能影响其他位。    printf("after shift, a = 0x%x.\n", a);*/   /*    //8.用C语言将一个寄存器的bit7~bit17中的值加17(其余位不受影响)。    unsigned int a =0xc30288f8;    unsigned int b=0;    //第一步,先读出原来bit7~bit17的值,即bit7~bit17不变,将其他位全部清零    b=a&(0b11111111111<<7);    b>>=7;    //第二步,给这个值加17    b+=17;    //第三步,将a的bit7~bit17的值清零,当然不能影响其他位    a&=~(0b11111111111<<7);    //第四步,将第二步算出的值写入bit7~bit17中    a|=b<<7;    printf("after shift, a = 0x%x.\n", a);*/ /*     //9.用C语言给一个寄存器的bit7~bit17赋值937,同时给bit21~bit25赋值17.    unsigned int a =  0xc30288f8;    a&=~(0b11111111111<<7);//第一步,先将bit7~bit17全部清零,其他位不变    a|=(937<<7);//第二步,再将937写入bit7~bit17即可,当然不能影响其他位。    a&=~(0b11111<<21);//第一步,先将bit21~bit25全部清零,其他位不变    a|=(17<<21);//第二步,再将17写入bit21~bit25即可,当然不能影响其他位。    printf("after shift, a = 0x%x.\n", a);    //也可以将上面的步骤合一    a&=~((0b11111111111<<7)|(0b11111<<21));//第一步,先将bit7~bit17全部清零,其他位不变    a|=((937<<7)|(17<<21));//第二步,再将937写入bit7~bit17即可,当然不能影响其他位。    printf("after shift, a = 0x%x.\n", a);*/}

二、位操作的宏定义

//用宏定义将32位数x的第n(bit0为第1)置位

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

//用宏定义将32位数x的第n(bit0为第1)清零

#define CLEAR_BIT_N(x,n) (x & (~(1U<<(n-1))))

//用宏定义将32位数x的第n位到第m(bit0为第1)置位

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

//用宏定义将32位数x的第n位到第m(bit0为第1)清零

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

//用宏定义获取32位数x的第n位到第m(bit0为第1)的部分

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


原创粉丝点击