1
C/C ++程序设计
1.2.9.1 9.1 位运算符

9.1 位运算符

位运算的操作数只能是整型或字符型,不能是浮点型数据,而且操作数都是以补码形式参与运算的,表9-1是C语言中提供的6种位运算符。

表9-1 位运算符

img325

9.1.1 按位与运算符

按位与运算符“&”是双目运算符。按位与运算规则如表9-2所示。

表9-2 按位与运算符

img326

功能:参与运算的两数各对应的二进制位相与。只有对应的两个二进制位均为1时,结果位才为1,否则为0。

(1)正数的按位与运算例如:

计算10&5,我们需要先把十进制数转换为补码形式,再进行按位与运算,结果是0,计算如下:

img327

(2)负数的按位与运算

例如:

计算-9&-5,结果是-13,计算如下:

第1步:先转换为补码形式。

img328

第2步:补码进行按位与运算。

img329

第3步:将结果转换为原码。

补码:1111 0011,反码:1111 0010,原码:1000 1101,原码:-13。

(3)按位与的作用

按位与运算通常用来对某些位清0或保留某些位。例如把整型变量a的高8位清0,保留低8位,可以使用a&255运算(255的二进制数形式为0000000011111111)。

例如,有一个数是0110 1101,我们希望保留从右边开始第3、4位,以到达程序的某些要求,我们可以这样运算:

img330

9.1.2 按位或运算符

按位或运算符“|”是双目运算符。其运算规则如表9-3所示。

表9-3 按位或运算符

img331

功能:参与运算的两数各对应的二进制位相或。只要对应的两个二进制位有一个为1时,结果位就为1,否则为0。

参与运算的两个数均以补码出现。

例如:计算10|5,结果是15,运算如下:

img332

此运算常用来将源操作数某些位置1,其他位不变。我们首先设置一个二进制掩码,执行按位或运算,把其中特定位置1,其他位为0。

例如有一个数是0000 0011,我们希望把它从右边开始第3、4位置为1,其他位不变,我们可以写成:

img333

即3|12=15。

9.1.3 按位异或运算符

按位异或运算符“^”是双目运算符。其运算规则如表9-4所示。

表9-4 按位异或运算符

img334

功能:参与运算的两数各对应的二进制位相异或,当两对应的二进制位相异时,结果为1。

例如:10^5运算过程如下:

img335

所以10^5=15。

充分利用按位异或的特性,可以实现以下效果:

(1)设置一个二进制掩码,执行按位求异或运算,设置特定位为1,可以使特定位的值取反;设置掩码中除特定位外其他位为0,可以保留原值。设有0111 1010,要使其低4位翻转,即1变为0,0变为1,可以将它与0000 1111进行按位异或运算,即:

img336

(2)不引入第三变量,交换两个变量的值。

要将a和b的值互换,可以用以下赋值语句实现:

a=a^b;

b=b^a;

a=a^b;

分析如下:(按位异或满足交换率)

a=a^b;

b=b^a=b^a^b=b^b^a=0^a=a;

a=a^b=a^b^a=a^a^b=0^b=b;

假设a=3、b=4,验证如下:

img337

9.1.4 按位取反运算符

按位取反运算符“~”为单目运算符,具有从右至左的结合性。其功能是对参与运算的数的各二进制位按位求反。例如~9的运算为:~(0000 1001),结果为:(1111 0110),如果表示无符号数是246,如果表示有符号数是-10。

9.1.5 左移运算符

左移运算符“<<”是双目运算符。其功能是把“<<”左边的操作数的各二进位全部左移若干位,由“<<”右边的操作数指定移动的位数。

左移运算过程如下所示:

二进制码:00000001,表示十进制数n=1;

n<<1二进制码:00000010,表示十进制数n=2;

n<<2二进制码:00000100,表示十进制数n=4;

n<<3二进制码:00001000,表示十进制数n=8;

n<<4二进制码:00010000,表示十进制数n=16;

n<<5二进制码:00100000,表示十进制数n=32;

n<<6二进制码:01000000,表示十进制数n=64;

n<<7二进制码:10000000,表示十进制数n=128;

n<<8二进制码:00000000,表示十进制数n=0。

如果数据在左移时值不超出指定字节范围,每左移一位相当于乘以2的n次幂。

9.1.6 右移运算符

右移运算符“>>”是双目运算符。其功能是把“>>”左边的操作数的各二进位全部右移若干位,“>>”右边的操作数指定移动的位数。

右移运算根据操作数是否有符号,分为无符号数右移和有符号数右移。无符号数右移n位时,丢弃右边n位数据,并在左边填充0。有符号数右移还可以分为算术右移和逻辑右移。算术右移是指有符号数右移时,左边以符号位填充;逻辑右移和无符号时右移一样,左边以0填充。

算术右移过程如下所示:

二进制码:10000000,表示十进制数n=-128;

n>>1二进制码:11000000,表示十进制数n=-64;

n>>2二进制码:11100000,表示十进制数n=-32;

n>>3二进制码:11110000,表示十进制数n=-16;

n>>4二进制码:11111000,表示十进制数n=-8;

n>>5二进制码:11111100,表示十进制数n=-4;

n>>6二进制码:11111110,表示十进制数n=-2;

n>>7二进制码:11111111,表示十进制数n=-1;

n>>8二进制码:11111111,表示十进制数n=-1。

如果数据在右移时值不超出指定字节范围,每右移一位相当于除以2的n次幂。