C++ 位操作 笔试题

某医疗器械公司2014年笔试题:

编写程序,对给定整型变量a,将bit4做设置和清零操作。

//code blocks 13.12
//GNU gcc complier
#include <stdio.h>
#include <stdlib.h>
#define Bit3 (0X01<<3)
int main()
{
    int a=15 ;      // 0000 1111
    printf("size of int:%d\n",sizeof(int));
    printf("原大小:%d\n", a);

    a &= ~Bit3;     //清零, 0000 0111
    //a &= ~(1<<3);
    printf("清零后:%d\n", a);

    a |= Bit3;     //置位, 0000 1111
    //a |= (1<<3);
    printf("置位后:%d\n", a);

    a ^= Bit3;     //取反, 0000 0111
    //a ^= (1<<3);
    printf("取反后:%d\n", a);
    // 另外一种方法
    printf("另外一种方法:\n");
    int c=a%8;//取末尾3位
    int b=a/8;//高位
    if(b%2==0)//set
        b++;
    a=b*8+c;
    printf("置位后:%d\n", a);
    if(b%2==1)//clear
        b--;
    a=b*8+c;
    printf("清零后:%d\n", a);

    return 0;
}
运行效果:


C++中的位操作包括两种:传统的C语言方式的位操作和C++中利用bitset容器进行的位操作。
 
****** 一、传统的C方式位操作:******
 
1.基本操作:
使用一个unsigned int变量来作为位容器。

2.位操作符:
|:按位或操作,result = exp1 | exp2;当exp1和exp2中对应位中有一个为1时,则result中对应位为1,否则为0.
应用特点:与0位“或”相应的位不变,与1位“或”设置相应的位为1.
因此用于:设置某一位为1,而保证其它的位不变。比如:result |= (1<<12)将设置result的第12位为1.
也常用于:给某个位属性值附加上另一个属性值,比如:result |= exp;这里相当于给result附加上exp的属性。
 
&:按位与操作,result = exp1 & exp2;当exp1和exp2中对应的位都为1时,result中对应的位才为1.
应用特点:与0位“与”相应的位为0,与1位“与”相应的位不变。0与1“与”结果为0,1与1“与”结果为1,所以也就是说bit & 1 = bit,与1进行“与”操作不改变本身。
因此用于:设置某一位为0,而保证其它的位不变。比如:result &= ~(1<<12)将设置result的第12为0.
也常用于:获得某个属性的某一位或某几位。比如:result & 3 将获得result的最低的两位。再比如截取一个32位数字的低8位等等。
也常用于:测试某个属性是否等于或包含特定的值。比如:if(result & exp)...
 
^:按位异或操作符,result = exp1 ^ exp1;当exp1和exp2中对应位的值不相同时,result对应的位为1
应用特点:1)0与1“异或”结果位1,1与1“异或”结果位0,也就是说bit ^ 1 = ~bit,与1“异或”相当于将特定的位取反。
          2)1与0“异或”结果位1,0与0“异或”结果位0,也就是说bit ^ 0 = bit,与0“异或”将保持特定的位不变。
因此用于:将某一特定位取反,而保证其它的位不变。比如:result ^= (1<<12)将result的第12位取反。
也常用于:将自己清0,比如:result ^= reslut;将使result所以位都变成0.
 
~:反转操作符,将位容器中的所以位都反转,将1变成0,0变成1。
 
<<:按位左移操作符,exp << n;将容器中的所有位向左移n位,空出的位用0填补。
>>:按位右移操作符,exp >> n;将容器中的所有位向右移n位,空出的位用0填补。
 
3.C方式位操作总结:
设置特定的位用|;
清除特定的位用&;
取反特定的位用^;
取反所有的位用~;
 
****** 二、C++中bitset容器来操作位:******
1.头文件:
#include <bitset>
2.声明一个容器:
(a)声明一个指定位数n所有位都为0的空容器:
   bitset<int n> bits;
(b)声明一个指定位数n并将用相应值来初始化容器:
   bitset<int n> bits(int m);
   bitset<int n> bits(string&);
总结:bitset模板类中类型参数传递容器的位数,而构造函数参数通过一个int或一个string&值来从右至左初始化容器中的相应值。
3.bitset的基本用法:
4.bitset与传统C位操作及字符串的转换:
可以通过to_string()成员函数将容器输出为一个string字符串;
可以通过to_long()成员函数将容器输出到传统的用于C风格的位容器中。
5.bitset支持所有位操作
6.位操作的例子:
将一个32位的整数输出成二进制形式:
//C的方式:
int i = 343543;
for(int j=31; j>=0; --j)
   cout << ((i >> j) & 1);

//C++的方式:
int i = 343543;
bitset<32> intBit(i);
   cout << intBit.to_string() << endl;

//测试一个数字含有多少个1位:
int count(int x)
{
    int n = 0;
    while(x) { 
       x &= (x-1); //将x的最右边的1位变成0
       ++n;
    }
    return n;
}
//测试一个数字含有多少个0位:
sizeof(x)*8 - count(x);

//测试一个数字的奇偶性:
只需测试最右位:为0则是偶数;位1则是奇数;if(x & 1)奇数; else 偶数;

///检测一个无符号数是不为2的次方:
if(x & (x-1) == 0) true; else false;

    ///二进制补码运算公式:(摘录自网上资料)
    -x = ~x + 1 = ~(x-1);
    ~x = -x-1;
    ~(-x) = x-1;
    x+y = x - ~y-1 = (x|y)+(x&y);
    x-y = x + ~y + 1 = (x|~y) - (~x&y);
    x^y = (x|y) - (x&y);
    x|y = (x& ~y) + y;
    x&y = (~x|y)- ~x;
    ///x == y:
    ~(x-y|y-x);
    ///x != y:
    x-y|y-x;
    ///x < y:
    (x-y)^((x^y)&((x-y)^x));
    ///x <= y:
    (x|~y)&((x^y)|~(y-x));
    ///x < y:
    (~x&y)|((~x|y)&(x-y)); ///无符号x,y的比较
    ///x <= y:
    (~x|y)&((x^y)|~(y-x)) ///无符号x,y的比较
    ///使用位运算的无分支代码:
    ///计算绝对值:
    int abs(int x)
    {
        int y;
        y = x >> 31;
        return (x^y)-y; ///or:(x+y)^y
    }
    ///符号函数:
    sign(int x)
    {
        return (x>>31)|
                (unsigned(-x))>>31; //x=-2的31次方时失败
    }
    ///三值比较:cmp(x, y) = -1(x<y);0(x==y);1(x>y)
    int cmp(int x, int y)
    {
        return (x>y)-(x-y);
    }



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值