Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1360442
  • 博文数量: 704
  • 博客积分: 10140
  • 博客等级: 上将
  • 技术积分: 6230
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-15 20:41
文章分类

全部博文(704)

文章存档

2013年(1)

2012年(16)

2011年(536)

2010年(151)

分类:

2011-11-07 22:01:33

原文地址:C/C++中的位操作的技巧 作者:digdeep126

【说明:本文参考了网上相关内容,做了补充和修改。】
 
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
2.声明一个容器:
(a)声明一个指定位数n所有位都为0的空容器:
   bitset bits;
(b)声明一个指定位数n并将用相应值来初始化容器:
   bitset bits(int m);
   bitset bits(string&);
总结:bitset模板类中类型参数传递容器的位数,而构造函数参数通过一个int或一个string&值来从右至左初始化容器中的相应值。
3.bitset的基本用法:
4.bitset与传统C位操作及字符串的转换:
可以通过to_string()成员函数将容器输出为一个string字符串;
可以通过to_long()成员函数将容器输出到传统的用于C风格的位容器中。
5.bitset支持所有位操作
6.位操作的例子:
将一个32位的整数输出成二进制形式:
  1. //C的方式:
  2. int i = 343543;
  3. for(int j=31; j>=0; --j)
  4.    cout << ((i >> j) & 1);

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

  9. //测试一个数字含有多少个1位:
  10. int count(int x)
  11. {
  12.     int n = 0;
  13.     while(x) {
  14.        x &= (x-1); //将x的最右边的1位变成0
  15.        ++n;
  16.     }
  17.     return n;
  18. }
  19. //测试一个数字含有多少个0位:
  20. sizeof(x)*8 - count(x);

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

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

  25.     ///二进制补码运算公式:(摘录自网上资料)
  26.     -x = ~x + 1 = ~(x-1);
  27.     ~x = -x-1;
  28.     ~(-x) = x-1;
  29.     x+y = x - ~y-1 = (x|y)+(x&y);
  30.     x-y = x + ~y + 1 = (x|~y) - (~x&y);
  31.     x^y = (x|y) - (x&y);
  32.     x|y = (x& ~y) + y;
  33.     x&y = (~x|y)- ~x;
  34.     ///x == y:
  35.     ~(x-y|y-x);
  36.     ///x != y:
  37.     x-y|y-x;
  38.     ///x < y:
  39.     (x-y)^((x^y)&((x-y)^x));
  40.     ///x <= y:
  41.     (x|~y)&((x^y)|~(y-x));
  42.     ///x < y:
  43.     (~x&y)|((~x|y)&(x-y)); ///无符号x,y的比较
  44.     ///x <= y:
  45.     (~x|y)&((x^y)|~(y-x)) ///无符号x,y的比较
  46.     ///使用位运算的无分支代码:
  47.     ///计算绝对值:
  48.     int abs(int x)
  49.     {
  50.         int y;
  51.         y = x >> 31;
  52.         return (x^y)-y; ///or:(x+y)^y
  53.     }
  54.     ///符号函数:
  55.     sign(int x)
  56.     {
  57.         return (x>>31)|
  58.                 (unsigned(-x))>>31; //x=-2的31次方时失败
  59.     }
  60.     ///三值比较:cmp(x, y) = -1(x<y);0(x==y);1(x>y)
  61.     int cmp(int x, int y)
  62.     {
  63.         return (x>y)-(x-y);
  64.     }

阅读(279) | 评论(0) | 转发(0) |
0

上一篇:getopt 函数分析

下一篇:printf的格式修饰串

给主人留下些什么吧!~~