C/C++位操作符号详解
C/C++位操作符号详解一、位运算:|按位或操作符:result=exp1|exp2;当exp1和exp2中对应位中至少有一个为1时,result中对应位为1,否则为0。& 按位与操作符::result=exp1&exp2;当exp1和exp2中对应位全为1时,result中对应位为1,否则为0。^按位异或或操作符:result=exp1^exp2;当exp1和exp2中对应位不相同时,resul
C/C++位操作符号详解
一、位运算:
| 按位或操作符:result=exp1|exp2;当exp1和exp2中对应位中至少有一个为1时,result中对应位为1,否则为0。
& 按位与操作符::result=exp1&exp2;当exp1和exp2中对应位全为1时,result中对应位为1,否则为0。
^ 按位异或或操作符:result=exp1^exp2;当exp1和exp2中对应位不相同时,result中对应位为1,否则为0。
~ 按位取反(反转)操作符:将位容器中的所有位都反转,1变为0,0变为1。
|=,&=,^= 分别对应|&^三种操作符的复合操作符。
应用:(不用中间变量交换两个值)
void myswap( int &a, int &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
原因:a^b^b 之后,a的值不变。
另解:
a = a + b;
b = a - b;
a = a - b;
但此种方法可能有溢出,没有第一种方法好。
二、定点数的移位运算
1、什么样的数据类型可以直接移位
char、short、int、long、unsigned char、unsigned short、unsigned int、unsigned long都可以进行移位操作,而double、float、bool、long double则不可以进行移位操作。
2、有符号数据类型的移位操作
对于char、short、int、long这些有符号的数据类型:
- 对负数进行左移:符号位始终为1,其他位左移 ,后面添0
- 对正数进行左移:所有位左移,即 <<,可能会变成负数
- 对负数进行右移:左边添1 ,右边丢弃。
- 对正数进行右移:所有位右移,即 >>
3、无符号数据类型的移位操作
对于unsigned char、unsigned short、unsigned int、unsigned long这些无符号数据类型,没有特殊要说明的,使用<< 和 >> 操作符就OK了
移位详细原理:
定点数的移位运算也称为移位操作。左移或右移n位相当于乘以或除以2的n次方。当计算机没有乘(除)运算线路时,可以采用移位和加法相结合,实现乘(除)运算。机器数字长往往是固定的,当机器数左移或右移时,必然会使其低位或高位出现空位。对空出的空位应该添补0还是1与机器数采用有符号数还是无符号数有关。有符号数的移位称为算术移位,无符号数的移位称为逻辑移位。
(1) 算术移位:
不同码制机器数算术移位后的空位添补规则
|
由上表可得出如下结论:
(1)机器数为正时,不论左移或右移,添补代码均为0。
(2)由于负数的原码其数值部分与真值相同,故在移位时只要使符号位不变,其空位均添0。
(3)由于负数的反码其各位除符号位外与负数的原码正好相反,故移位后所添的代码应与原码相反,不论左移或右移,即全部添1。
(4)分析任意负数的补码可发现,当对其由低位向高位找到第一个“1”时,在此“1”左边的各位均与对应的反码相同,而在此“1”右边的各位(包括此“1”在内)均与对应的原码相同,即添0;右移时空位出现在高位,则添补的代码应与反码相同,即添1。
(2)逻辑移位:逻辑移位的规则是逻辑左移时,高位移出,低位添0;逻辑右移时,低位移出,高位添0。
以下是一种简明的说法:
对于无符号数的移位(逻辑移位)很简单,直接变成2进制,经过移位后, 一端的位被"挤掉",而另一端空出的位以0 填补。
而对于有符号数移位(算术移位)则相对复杂一点,如果符号位为0(即正数),其移位效果与无符号数 移位一致。
容易出错的是负数移位。负数移位需先将负数变成计算机的补码形式,即保留符号位而其它位取反加1。如 int16型的-15,正常翻译为1000 0000 0000 1111,保留符号位其它位取反加1,变成1111 1111 1111 0001(0xFFF1)。变成这种形式后就可以对其进行移位了,左移,保留符号位,左边被挤掉的不管,右边填0;而右移的时候略有不同,保留符号位,右边被挤掉的部分丢弃,而高位填符号位1。如-15,右移3位,则变成FFFE(-2)。显然有符号数移位并不等效于乘法或除法。
如果将有符号数强制类型转换为无符号,则将其2进制补码形式翻译为无符号数即可。如
short aa = -15;
unsigned short bb;
bb = (unsigned short) aa;
则bb变成0xFFF1(65521),实际上就是-15的计算机表示。
例:设机器数字长为8位(含一位符号位),若A=±26,写出三种机器数左、右移一位和两位后的表示形式及对应的真值,并分析结果的正确性。
解:(1)A=+26=(+11010)2
则[A]原=[A]补 =[A]反=0,0011010
移位结果表示如下:
|
可见,对于正数,三种机器数移位后符号位不变,左移时最高数位丢1,结果出错;右移时最低数位丢1,影响精度。
(2)A=-26=(-11010)2
三种机器数移位结果示于下表。
|
可见,对于负数,三种机器数移位后符号位均不变。负数的原码左移时,高位丢1,结果出错;低位丢1,影响精度。负数的补码左移时,高位丢0,结果出错;低位丢1,影响精度。负数的反码左移时,高位丢0,结果出错;低位丢0,影响精度。
应用:(不用比较运算符来比较大小)
int mymin(int a, int b )
{
int mask = (a - b)>>31;
return (a & mask) | (b & ~mask);
}
int mymax(int a, int b )
{
int mask = (a - b)>>31;
return (a & ~mask) | (b & mask);
}
参考:http://blog.sina.com.cn/s/blog_4cc4ca890100c9c6.html
http://blog.csdn.net/howema/archive/2008/11/19/3334596.aspx
更多推荐
所有评论(0)