c++ 位操作

本篇由作者原创(部分参考)

注意:位操作只适用于整型数据的操作,对于float型和double型数据编译器会报错。

位操作有与、或、异或、取反、左移、右移六种,符号及运算规则如下:


 符号


描述


运算规则


&



两个位都为1时,结果才为1


|



两个位都为0时,结果才为0


^


异或


两个位相同为0,相异为1


~


取反


0变1,1变0


<<


左移


各二进位全部左移若干位,高位丢弃,低位补0


>>


右移


各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)

注意:1.位操作的优先级比较低,应该使用括号保证提前运算。

   2.对于移位操作来讲必须要注意是算术移位还是逻辑移位(算术左移、右移主要进行有符号数的倍增、倍减。逻辑左移、   右移主要进行无符号数的倍增、倍减。)

      逻辑移位:不考虑符号位,也就是不考虑正负数的移位(逻辑移位不管是左移还是右移都是空缺处补0)

      算术移位:考虑符号位,也就是正负数的移位(算数移位要保证符号位不改变)

          1)其中算术左移和逻辑逻辑左移的思想一样,缺位补0。

          2)算术右移的移位过程中,缺位由符号位决定(符号位是1,缺位补1。符号位是0,缺位补0)

注:(数据在计算机以补码存储)补码在计算机算术左移过程中符号位可能发生改变(溢出)。



位操作可以对某字节中的某段字段赋值、修改、取值(需要借助移位)等操作

实例:(这里以对字节为单位进行位操作,获取字节中的10)

#define  TEMP_NUMBER_INITINAL  0x00000000    //十六进制表示 0

#define  TEMP_NUMBER  0x000000a0   //十六进制表示 160

1 void main(){
2       int   number=NULL;
3       number = TEMP_NUMBER;
4       cout<<(number>>8)<<endl;//此时输出的是10
5 }        

位操作的一般应用:

1.判断奇偶

只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if (a & 1 == 0)代替if (a % 2 == 0)来判断a是不是偶数。

下面程序将输出0到100之间的所有奇数。

[cpp] view plaincopy

  1. for (i = 0; i < 100; ++i)
  2. if (i & 1)
  3. printf("%d ", i);
  4. putchar(‘\n‘);

2.交换两数

一般的写法是:

[cpp] view plaincopy

  1. void Swap(int &a, int &b)
  2. {
  3. if (a != b)
  4. {
  5. int c = a;
  6. a = b;
  7. b = c;
  8. }
  9. }

可以用位操作来实现交换两数而不用第三方变量:

[cpp] view plaincopy

  1. void Swap(int &a, int &b)
  2. {
  3. if (a != b)
  4. {
  5. a ^= b;
  6. b ^= a;
  7. a ^= b;
  8. }
  9. }

可以这样理解:

第一步  a^=b 即a=(a^b);

第二步  b^=a 即b=b^(a^b),由于^运算满足交换律,b^(a^b)=b^b^a。由于一个数和自己异或的结果为0并且任何数与0异或都会不变的,所以此时b被赋上了a的值。

第三步 a^=b 就是a=a^b,由于前面二步可知a=(a^b),b=a,所以a=a^b即a=(a^b)^a。故a会被赋上b的值。

再来个实例说明下以加深印象。int a = 13, b = 6;

a的二进制为 13=8+4+1=1101(二进制)

b的二进制为 6=4+2=110(二进制)

第一步 a^=b  a = 1101 ^ 110 = 1011;

第二步 b^=a  b = 110 ^ 1011 = 1101;即b=13

第三步 a^=b  a = 1011 ^ 1101 = 110;即a=5

3.变换符号

变换符号就是正数变成负数,负数变成正数。

如对于-11和11,可以通过下面的变换方法将-11变成11

1111 0101(二进制) –取反-> 0000 1010(二进制) –加1-> 0000 1011(二进制)

同样可以这样的将11变成-11

0000 1011(二进制) –取反-> 0000 1010(二进制) –加1-> 1111 0101(二进制)

因此变换符号只需要取反后加1即可。完整代码如下:

[cpp] view plaincopy

  1. //by MoreWindows( http://blog.csdn.net/MoreWindows )
  2. #include <stdio.h>
  3. int SignReversal(int a)
  4. {
  5. return ~a + 1;
  6. }
  7. int main()
  8. {
  9. printf("对整数变换符号 --- by MoreWindows( http://blog.csdn.net/MoreWindows )  ---\n\n");
  10. int a = 7, b = -12345;
  11. printf("%d  %d\n", SignReversal(a), SignReversal(b));
  12. return 0;
  13. }

4.求绝对值

位操作也可以用来求绝对值,对于负数可以通过对其取反后加1来得到正数。对-6可以这样:

1111 1010(二进制) –取反->0000 0101(二进制) -加1-> 0000 0110(二进制)

来得到6。

因此先移位来取符号位,int i = a >> 31;要注意如果a为正数,i等于0,为负数,i等于-1。然后对i进行判断——如果i等于0,直接返回。否之,返回~a+1。完整代码如下:

[cpp] view plaincopy

  1. //by MoreWindows( http://blog.csdn.net/MoreWindows )
  2. int my_abs(int a)
  3. {
  4. int i = a >> 31;
  5. return i == 0 ? a : (~a + 1);
  6. }

现在再分析下。对于任何数,与0异或都会保持不变,与-1即0xFFFFFFFF异或就相当于取反。因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值。所以可以对上面代码优化下:

[cpp] view plaincopy

  1. //by MoreWindows( http://blog.csdn.net/MoreWindows )
  2. int my_abs(int a)
  3. {
  4. int i = a >> 31;
  5. return ((a ^ i) - i);
  6. }
时间: 2024-11-07 00:50:10

c++ 位操作的相关文章

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,为啥要用补码 计算机中的符号数有三种表示方法,即原码.反码和补码.三种表示方法均有符号位和数值位两部分,符号位都是用0表示"正",用1表示"负",而数值位,三种表示方法各不相同. 在计算机系统中,数值一律用补码来表示和存储.原因在于,使用补码,可以将符号位和数值域统一处理:同时,加法和减法也可以统一处理.此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路.(来自百度百科) 2,补码的求法: 正数的补码和原码相同: 负数是对应正数

C/C++位操作

异或:不同为1,相同为0.可以记为:"异"为不同,不同为1. C方式位操作总结: 设置特定的位用|; 清除特定的位用&; 取反特定的位用; 取反所有的位用~; 引用自

在32位、64位操作系统下各数据类型所占的字节数

点击打开链接 在32位.64位系统当中,唯一改变的是指针的长度;在32位系统当中是4个字节.64位则是8个字节.所谓的32位.64位,这个指的是寄存器的位宽. 32位平台下结果: 64位平台下结果: 一.下面几点是值得大家注意的: 1.关于 int 的取值范围,缺省的int数值范围是由编译器设计者决定的,通常都是机器最为自然高效的位数.甚至,我们在32位的机器上,前提没有什么指令可以高效的的处理更短的整型值,我们可以将short.int.long都设置成32位. 2.浮点数在缺省的情况下 表示的

关于java按位操作运算

<1>.在了解位移之前,先了解一下正数和负数的二进制表示形式以及关系:举例15和-15: 15 的原码: 00000000 00000000 00000000 00001111     补码: 11111111 11111111 11111111 11110000                 +1 = -15的原码:11111111 11111111 11111111 11110001 负数的原码即为:正数的原码取反,再加1. <2>位移操作:(只针对 int类型的数据有效,j

MySQL学习2:Windows 64位操作系统下安装和配置MySQL

一安装方式 MySQL安装文件分为两种,一种是MSI格式的,一种是ZIP格式的.下面来看看这两种方式: MSI格式的可以直接点击安装,按照它给出的安装提示进行安装,Windows操作系统下一般MySQL将会安 装在C:\Program Files\MySQL该目录中. ZIP格式是自己解压,解压缩之后其实MySQL就可以使用了,但是要进行配置.这个可以在网上随便找,给出很 多自定义安装和配置的详细步骤.推荐的链接:http://jingyan.baidu.com/article/f79b7cb3

netty中的位操作

看了PoolChunk源码,好多位操作,对这些位操作理解不到位,看起来很是吃力,不知道为什么要这么做,但是是性能更好 1:大小为2 的冥的数加1 怎么操作 size^1; 2: <=比较   mask=~(pageSize-1) num & mask  !=0   那么num <mask 4:两个数互补 mask= -(constNum) mask & num==0

位操作的一些常用用法

参考: 位操作基础篇之位操作全面总结 位操作有6种基本操作符,按照优先级分别是: 取反   - 移位   <<  >> 与      & 异或   ^ 或      | 常用的用法有: 1 判断偶数,判断最低位是0还是1即可,比求模快 1 x % 2 != 0 //x正负都可以判断:不用x%2 == 1,因为如果x为负奇数,x%2=-1 2 x & 0x1 == 0 2 交换两个数,不用中间变量 1 void mySwap(int &a, int &

c语言中的位移位操作

先要了解一下C语言里全部的位运算都是指二进制数的位运算.即使输入的是十进制的数,在内存中也是存储为二进制形式. “<<”使用方法: 格式是:a<<m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向左移动m位,高位移出后,低位补0. “>>”使用方法: 格式是:a>>m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向右移动m位,低位移出后,高位补0 C语言中的移位操作,内容不多.只是有些地方你不注意,就疏

【C语言天天练(二二)】位操作

C的位运算符 1.二进制反码或按位取反:~ ~(10011010) = (01100101). 假设val是一个unsigned char,~val不改名原来val的值. 2.位与:& 二进制运算符&通过对两个操作数逐位进行比较产生一个新值. (10010011)&(00111101)=(00010001). C中的一个组合的位与赋值运算符:&=. 3.位或:| 二进制运算符|通过对两个操作数逐位进行比较产生一个新值. (10010011)|(00111101)=(1011