第 13 章 位运算

54

Click here to load reader

Upload: erin-lucas

Post on 01-Jan-2016

84 views

Category:

Documents


5 download

DESCRIPTION

第 13 章 位运算. 13.1 位运算符和位运算. 13.1 位运算符和位运算. 由于 C 语言是介于高级语言和汇编语言之间的一种计算机 语言,它可用于开发系统软件,并且可以直接对地址进行运算 ,因此, C 语言提供了位运算的功能。 所谓位运算是指二进制位的运算。在系统软件中,常常需 要处理二进制位的问题。例如,将一个存储单元中存储的数据 的各二进制位,左移位或右移位,两个数按位相加等。位运算 是 C 语言不同于其它高级语言的又一特色。. 13.1 位运算符和位运算. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

第 13 章 位运算

Page 2: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

13.1 位运算符和位运算

Page 3: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-3

13.1 位运算符和位运算 由于 C 语言是介于高级语言和汇编语言之间的一种计算机语言,它可用于开发系统软件,并且可以直接对地址进行运算,因此, C 语言提供了位运算的功能。 所谓位运算是指二进制位的运算。在系统软件中,常常需要处理二进制位的问题。例如,将一个存储单元中存储的数据的各二进制位,左移位或右移位,两个数按位相加等。位运算是 C 语言不同于其它高级语言的又一特色。

Page 4: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-4

13.1 位运算符和位运算 前面介绍的各种运算都是以字节作为最基本单位进行的。但在

很多系统程序中常要求在位 (bit) 一级进行运算或处理。 C 语言之所以具有广泛的用途和强大的生命力,就在于它既具有高级语言的特点,又具有低级语言的功能。因而 C 语言提供了位运算的功能,这使得 C 语言也能像汇编语言一样用来编写系统程序。

Page 5: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-5

13.1 位运算符和位运算

13.1.1 位运算符 位运算符的功能是对其操作数按其二进制形式逐位地进行逻辑运算或移位运算。由位运算的特点确定操作数只能是整数类型或字符类型的数据,不能是实型数据。 C 语言提供 6 种位运算符。

Page 6: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-6

表 13-1 位运算符

13.1 位运算符和位运算

Page 7: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-7

13.1 位运算符和位运算13.1.2 按位与运算 按位与运算符“ &” 是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为 1 时,结果位才为 1 ,否则为 0 。 0&0=0; 0&1=0; 1&0=0; 1&1=1

参与运算的数以补码方式出现。 例如: 9&5 可写算式如下: 00001001 (9 的二进制补码 )

& 00000101 (5 的二进制补码 )

  00000001 (1 的二进制补码 )

可见 9&5=1 。 按位与运算具有以下特征:

Page 8: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-8

13.1 位运算符和位运算( 1 )任何位上的二进制数只要和 0 进行与运算,该位即被屏蔽 ( 清零

) 。( 2 )任何位上的二进制数只要和 1 进行与运算,该位保留原值不变。 利用这一特征可以实现如下功能: ( 1 )清零。 如果想将一个单元清零,也就是使其全部二进制位为 0 ,只需与 0

进行与运算,即可达到清零的目的。例如: 12&0

00001010 (10 的二进制补码 )

& 00000000 (0 的二进制补码 )

00000000 (0 的二进制补码 )

Page 9: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-9

13.1 位运算符和位运算( 2 )取一个数的某些指定位。 如有一个整数 a ( 2 个字节),要想高 8 位清 0 ,保留低 8 位,可进行 a&255 运算 (255 的二进制数为 0000000011111111) 。如果想取 2 个字节中的高位字节,可进行 a&65280 ( 65280 的二进制数为 1111111100000000 )。( 3 )要想哪一位保留下来,就与一个数进行与运算,此数在该位取1 ,其它位取 0 。 例如, 85 ( 85 的二进制数为 01010101 ),想把其中左边第 3 、 4

、 7 、 8 位保留下来,设计一个数,其左边第 3 、 4 、 7 、 8 位为 1 其它位为 0 ,即十进制数 51 。将这两个数进行位与运算即可。

Page 10: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-10

13.1 位运算符和位运算例 13.1 验证 26&108 的结果。分析: a=00011010( 十进制数 26) , b=01101100( 十进制数 108) ,

则a&b=00001000( 十进制数 8) 。 00011010& 01101100 00001000根据上述分析编写的程序如下:#include <stdio.h>void main(){ int a=9,b=5,c; c=a&b; printf("a=%d\n b=%d\n a&b =%d\n",a,b,c);}

Page 11: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-11

13.1 位运算符和位运算例 13.2 编写一个程序,对两个整型变量、整型常量分别进行按位与运算,并输出它们的值。#include <stdio.h>void main(){ int x,y; x=25;y=568; printf("x&y:%d\n ",x&y); printf("3&14:%d\n ",3&14); printf("-3&14:%d\n ",-3&14); printf("12&12:%d\n ",12&12);}

Page 12: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-12

13.1 位运算符和位运算13.1.3 按位或运算 按位或运算符“ |” 是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为 1 时,结果位就为1 。 0|0=0 ; 0|1=1 ; 1|0=1 ; 1|1=1

参与运算的两个数均以补码出现。 例如: 9|5 可写算式如下: 00001001

| 00000101

00001101 ( 十进制为 13)

可见 9 |5=13 。

Page 13: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-13

13.1 位运算符和位运算按位或运算具有以下特征:( 1 )任何位上的二进制数只要和 1 进行或运算,该位即为 1 。( 2 )任何位上的二进制数只要和 0 进行或运算,该位保留原值不变

。利用这一特征可以实现如下功能: 按位或运算常用来对一个数的二进制位中一个或几个指定位置 1

。对应于 a 要置 1 的位, b 对应的位为 1 ,其余位为 0 。则 a 与 b 或就

可以使 a中指定位置 1 。例如:a=01100000 ,要使 a 的后 4 位置 1 ,则可设置 b 后 4 位为 1 ,其余位

为 0 ,即 b=00001111 。 01100000 | 00001111 01101111

Page 14: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-14

13.1 位运算符和位运算例 13.3 验证 26|108 的结果。分析: a=00011010( 十进制数 26) , b=01101100( 十进制数 108) 。则a|b=01111110( 十进制 126) 。 00011010

| 01101100

01111110

根据上述分析编写的程序如下:#include <stdio.h>

void main()

{ int a=9,b=5,c;c=a|b;printf("a=%d\nb=%d\n a|b=%d\n",a,b,c);

}

Page 15: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-15

13.1 位运算符和位运算

13.1.4 按位异或运算 按位异或运算符“ ^” 是双目运算符。其功能是参与运算

的两数各对应的二进位相异或,当两对应的二进位相异时,结果为 1 。 0^0=0; 0^1=1; 1^0=1; 1^1=0

参与运算数仍以补码出现。 例如, 9^5 可写成算式如下: 00001001

^ 00000101

00001100 ( 十进制为 12)

Page 16: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-16

13.1 位运算符和位运算位异或运算有以下方面的应用:( 1 )使特定位翻转。 假设有 01101011 ,想使其低 4 位翻转,即 1 变为 0 , 0 变为 1 。可以将它与 00001111 进行按位异或运算,结果为 01100100 ,结果值的低 4位恰好是原数低 4 位的翻转。

01101011 ^ 00001111 01100100 要使哪几位翻转,就将该几位置为 1 ,其余位置为 0 ,将原数与这个数进行按位异或运算即可。这是因为原数中的 1 与 1 进行 ^ 运算得0 ,原数中的 0 与 1 进行 ^ 运算得 1 。 例如,有 01111011 ,想使第 3 至 7 位翻转,只要与 00111110 进行按位异或运算即可。 01111011^ 00111110 01000101

Page 17: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-17

13.1 位运算符和位运算( 2 )与 0 进行异或运算,保留原值。例如: 13^0=13 00001101^ 00000000 00001101( 3 )交换两个变量的值,不用中间变量。 a=5,b=8 。如果想使 a 与 b 的值交换,可用以下赋值语句来实现: a=a^b; b=a^b; a=a^b; a=0101^ b=1000 a=1101

Page 18: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-18

13.1 位运算符和位运算 a=1101^ b=1000 b=0101 (十进制 5 ) a=1101^ b=0101 a=1000 (十进制 8 ) 可见,变量 a 与 b 的值进行了交换。 a=a^b ,实际上进行了下面

两步运算:

① b=b^a=b^(a^b)=b^a^b=a^b^b=a^(b^b)=a^0=a ② a=a^b=(a^b)^a=a^b^a=(a^a)^b=0^b=b

例 13.4 验证按位异或 26^108 运算。 分析: a=00011010( 十进制数 26) , b=01101100( 十进制数 108)

。则 a^b=01110110( 十进制 118) 。

Page 19: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-19

13.1 位运算符和位运算 00011010^ 01101100 01110110

根据上述分析编写的程序如下:#include <stdio.h>

void mian()

{ int a=26,b=108,c;

c=a^b;

printf("a=%d\n b=%d\n a^b=%d\n",a,b,c);

getch();

}

Page 20: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-20

13.1 位运算符和位运算程序运行结果:a=26

b=108

a^b=118

Page 21: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-21

13.1 位运算符和位运算13.1.5 按位求反运算 求反运算符“~”为单目运算符,具有右结合性。 其功能是,对参与运算的数的各二进制位进行“取反”运算。即:对应的二进制位为 0 时,结果为 1 ,为 1 时,结果为 0 。参与运算数均以补码出现。 例如, a=00000000 00011010 (十进制数 26 ), 则~ a=11111111 11100101 (十进制数 -27 )。 0000000000011010 ~ 1111111111100101 “ ~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其它运算符都高。例如:~ a&b, 先进行~ a 运算,然后进行 & 运算。

Page 22: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-22

13.1 位运算符和位运算例 13.5 验证按位求反运算~ 6 。程序如下: #include <stdio.h> void main(){ int a=6,b; b=~a; printf("a=%d\n~b=%xH",a,b);}程序运行结果: a=6; -b=fff9H 程序说明:程序是按照数据补码进行按位取反的,输出十进制数据运算较大,所以本例以十六进制输出6 (0000000000000110) ,则按位取反后~6 (1111111111111001) 。

Page 23: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-23

13.1 位运算符和位运算例 13.6 编程输出按位取反运算的值。程序如下:#include <stdio.h>void main(){ int x=-25; unsigned int y=0; printf("~25:%d\n ",~25); printf("~x:%d\n ",~x); printf("~y(1):%d\n ",~y); printf("~y(2):%u\n ",~y);}程序运行结果:~25:-26~x:24~y(1):-1~y(2):65535

Page 24: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-24

13.1 位运算符和位运算

13.1.6 左移运算 左移运算符“ <<” 是双目运算符。 其功能把“ <<” 左边的运算数的各二进位全部左移若干位,由“<<” 右边的数指定移动的位数,高位左移后溢出,舍弃不起作用,低位补 0 。 例如: a<<4 指把 a 的各二进位向左移动 4 位。 再如: a=00000011( 十进制 3) ,左移 4 位后为 00110000( 十进

制 48)

。左移一位相当于该数乘以 2 ,左移二位相当于该数乘以 22=4 ,左移

n 位相当于该数乘以 2n ,上面举的例子 3<<4=48 ,即 3乘了 24=16

Page 25: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-25

13.1 位运算符和位运算例 13.7 对整型变量 b 进行按位左移 2 位运算,输出左移运算后的值

。程序如下:#include <stdio.h>

void main()

{ unsigned a,b;

b=12; a=b<<2;

printf("a=%d\n",a);

}

程序运行结果:a=48

Page 26: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-26

13.1 位运算符和位运算13.1.7 右移运算 右移运算符“ >>” 是双目运算符。 其功能是把“ >>” 左边的运算数的各二进位全部右移若干位,移到右端的低位被舍弃,对于无符号数,高位补 0 。“ >>” 右边的数指定移动的位数。 例如: a=15

a>>2表示把 000001111 右移为 00000011( 十进制 3) 。应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补 0 ,而为负数时,符号位为 1 ,最高位是补 0 或是补 1 取决于编译系统的规定。 Turbo C 和很多系统规定为补 1 。右移一位相当于该数除以 2 ,右移 n 位相当于该数除以 2n 。

Page 27: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-27

13.1 位运算符和位运算例 13.8 先右移,后进行与运算。程序如下:#include <stdio.h>void main(){ unsigned a,b;printf("input a number:");scanf("%d",&a);b=a>>5;b=b&15;printf("a=%d\tb=%d\n",a,b);}程序运行结果:input a number:21↙a=21 b=0

Page 28: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-28

13.1 位运算符和位运算

13.1.8 不同长度的数据进行位运算 位运算的运算数可以是整型和字符型数据。如果两个运算数类型不同时位数也会不同。遇到这种情况,系统将自动进行如下处理: ( 1 )先将两个运算数右端对齐。 ( 2 )再将位数短的一个运算数往高位补充,即无符号数和正整数左侧用 0 补全;负数左侧用 1 补全;然后对位数相等的这两个运算数,按位进行位运算 。

Page 29: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-29

13.1 位运算符和位运算例 13.9 分析下面程序的运行结果。#include <stdio.h>void main( ){ char a='a',b='b'; int p,c,d; p=a; p=(p<<8)|b; d=p&0xff; c=(p&0xff00)>>8; printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);}

程序运行结果:a=97b=98c=97d=98

Page 30: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-30

13.1 位运算符和位运算

例 13.10 编写一个程序,实现一个无符号整数的循环左移 n 位。

分析:先将无符号整数 d 高端的 n 位数通过右移操作移至低端的 n 位上(高端全为 0 ),把结果存入中间变量 a 中。再通过左移运算将 d 左移 n 位(低端移入的全为 0 ),把结果存入另一中间变量 b 中。最后利用按位或运算将这两个中间变量中的内容“拼装”在一起,完成循环左移功能。

Page 31: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-31

13.1 位运算符和位运算#include <stdio.h>unsigned int left(unsigned int d,int n){ unsigned int a,b,c; a=d>>(16-n); b=d<<n; c=a|b; return(c);}

void main()

{ unsigned int d;

d=0x6271;

printf("%x\n",left(d,3));

}

程序运行结果:138b

Page 32: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-32

例 13.11 编写一个程序,将一个无符号整型的前 8 位和后 8 位交换。

分析:首先将 d 右移 8 位得到高 8 位数,把结果存入中间变量 a

中。再将 d 与 0377 (高 8 位全为 0 ,低 8 位全为 1 )进行按位与低 8

位数,将其左移 8 位放到高端,把结果存入中间变量 b 中。最后将 a 和 b

进行按位或得到最后结果。 根据上述分析编写的程序如下:

13.1 位运算符和位运算

Page 33: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-33

13.1 位运算符和位运算#include <stdio.h>unsigned int swap(unsigned int d){ unsigned int a,b,c; a=d>>8; b=(d&0377)<<8; c=a|b; return(c);}void main(){ unsigned int d; d=0x6271; printf("%x\n",swap(d));}程序运行结果:7162

Page 34: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

13.2 位段结构

Page 35: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-35

13.2 位段结构13.2.1 位段的概念 有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如,在存放一个开关量时,只有 0 和 1 两种状态,“真”或“假”用 1 或 0表示,用一位二进制位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域” 或“位段”。所谓“位段”是把一个字节中的二进位划分为几个不同

的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

13.2.2 位段结构的定义和位段变量的说明

Page 36: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-36

13.2 位段结构 C 语言中没有专门的位段类型,位段的定义要借助于结构体,即以二进制位为单位定义结构体成员所占存储空间,从而就可以按“位”来访问结构体中的成员。位段结构的定义与结构体定义相仿,其一般形式为: struct 位段结构名 { 位段列表 }; 其中位段列表的形式为: 类型说明符 位段名:位段长度 例如: struct bs { int a:8; int b:2; int c:6; };

Page 37: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-37

13.2 位段结构 位段变量的说明与结构变量说明的方式相同。可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:struct bs{ int a:8; int b:2; int c:1;}data; 说明 data 为 bs 变量,共占两个字节。其中位段 a占 8 位,位段 b占 2

位,位段 c占 6 位。 说明: ( 1 )一个位段必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位段时,应从下一单元起存放该位段。也可以有意使某位段从下一单元开始。

Page 38: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-38

13.2 位段结构例如:struct bs

{ unsigned a:4

unsigned :0 /* 空域 */

unsigned b:4 /* 从下一单元开始存放 */

unsigned c:4

}

在这个位段定义中, a占第一字节的 4 位,后 4 位填 0表示不使用,

b从第二字节开始,占用 4 位, c占用 4 位。 ( 2 )由于位段不允许跨两个字节,因此位段的长度不能大于一个字节的长度,也就是说不能超过 8 位二进位。

Page 39: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-39

13.2 位段结构 ( 3 )位段可以没有位段名,这时它只用来作填充或调整位置。无

名的位段是不能使用的。例如:struct k

{ int a:1

int :2 /* 该 2 位不能使用 */

int b:3

int c:2

};

从以上分析可以看出,位段在本质上就是一种结构类型,不过其成员是按二进位分配的 。

Page 40: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-40

13.2 位段结构13.2.3 位段的引用和结构体成员的引用相同,其一般形式为:位段变量名 . 位域名struct bs{ int a:8; int b:4; int c:1;}data;data.a ; data.b ; data.c ;表示引用变量 data 中的位段 a 、 b 、 c 。

Page 41: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-41

13.2 位段结构13.2.4 位段的赋值 位段可以在定义的同时赋初值,形式与结构体变量赋初值相同

。位段也可以进行赋值操作,例如:data.a=1 ;data.b=4 ;data.c=6 ;

Page 42: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-42

13.2 位段结构

13.2.5 使用位段的注意事项( 1 )位段可以初始化,形式与结构体变量赋初值相同,位段也可以进行赋值。 例如: data.b=2;

赋值时应注意位段的取值范围,例如: data.c=2; 就会产生错误的结果。因为 data.c 只占 1 位,只能取值 0 或 1 。 对于赋值语句: data.c=2; 系统并不报错,而是自动截取所赋值的低位: 2 的二进制码是 10 ,取低一位为 0 。所以 data.c 的值为 0

Page 43: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-43

13.2 位段结构( 2 )位段可以进行算术运算,系统自动将其转换成整型数。例如:data.b=5;

data.c=1;

data.a=data.b+data.c;

( 3 )可以用整型格式符( %d 、 %o 、 %x 、 %u )进行输出。例如: printf(“%d\n”,data.a);

( 4 )不能对位段求地址。 由于位段没有地址,所以不能对位段求地址,也不能通过scanf()函数给位段赋值,不能用指针变量指向位段。

Page 44: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-44

13.2 位段结构例 13.12 分析下面程序的运行结果。#include <stdio.h>void main(){ struct bs { unsigned a:1; unsigned b:3; unsigned c:4; }bit,*pbit; bit.a=1; bit.b=7; bit.c=15; printf("%d,%d,%d\n",bit.a,bit.b,bit.c); pbit=&bit; pbit->a=0; pbit->b&=3; pbit->c|=1; printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);}

Page 45: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-45

13.2 位段结构 程序中定义了位段结构体类型 bs ,三个位域为 a , b , c 。说明了bs 类型的变量 bit 和指向 bs 类型的指针变量 pbit 。这表示位段也是可以使用指针的。程序的 9 、 10 、 11三行分别给三个位段赋值。(应注意赋值不能超过该位段的允许范围 ) 程序第 12 行以整型量格式输出三个域的内容。第 13 行把位段变量 bit 的地址送给指针变量 pbit 。第 14 行用指针方式给位段 a重新赋值,赋为 0 。第 15 行使用了复合的位运算符“&=” ,该行相当于: pbit->b=pbit->b&3 位段 b 中原有值为 7 ,与 3

作按位与运算的结果为 3(111&011=011 ,十进制值为 3) 。同样,程序第 16 行中使用了复合位运算“ |=” ,相当于: pbit->c=pbit->c|1 其结果为 15 。程序第 17 行用指针方式输出了这三个段的值。

Page 46: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-46

13.2 位段结构例 13.13 编写一程序,输出位段变量的值。程序如下:#include <stdio.h>void mian(){ int x; struct kzds; { unsigned int qw:1; unsigned int zw:2; unsigned int hw:3; unsigned int mw:1; }x1,x2; x1.qw=1; x1.hw=5; x=x1.qw+x1.hw/2; printf("x1.qw =%u\n ", x1.qw); printf("x1.hw =%u\n ", x1.hw); printf("x =%d\n ", x);}

Page 47: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

13.3 程序举例

Page 48: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-48

13.3 程序举例 例 13.14 编写一个使用位运算复合赋值运算符的程序。程序如下:#include <stdio.h>void main(){ char a=9,b=9,c=9,d=9,e=9; a<<=1; /* 等价于 a=a<<1 */ b>>=1; /* 等价于 b=b>>1 */ c&=5; /* 等价于 c=c&5 */ d|=5; /* 等价于 d=d|5 */ e^=5; /* 等价于 e=e^5 */ printf("%d %d %d %d %d\n",a,b,c,d,e);}程序运行结果:18 4 1 13 12本程序中赋值表达式的处理过程与 += 、 -= 、 *= 、 /= 、 %= 相同

Page 49: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-49

13.3 程序举例 例 13.15 编写一个程序,其功能是将正整型数组中所有元素转

换为不大于它的最大偶数,并显示输出。 为了将一个正整数转换为不大于它的最大偶数,只需将该正整数所对应的二进制数的最低位清 0 即可,即用 0xfffe 与该正整数做

“按位与”运算。根据上述分析编写的程序如下:

Page 50: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-50

13.3 程序举例#include <stdio.h>void main(){ int i; int a[10]={23,14,24,31,46,55,33,68,27,40}; for(i=0;i<10;i++) printf("%5d",a[i]);

printf("\n");

for(i=0;i<10;i++)

a[i]=a[i]&0xfffe; /* 将正整数转换为不大于它的最大偶数 */

for(i=0;i<10;i++)

printf("%5d",a[i]);

printf("\n");

}

程序运行结果:23 14 24 31 46 55 33 68 27 4022 14 24 30 46 54 32 68 26 40

Page 51: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-51

13.3 程序举例 例 13.16 编写一个程序,其功能是将正整型数组中所

有元素转换为不小于它的最小奇数,并显示输出。 为了将一个正整数转换为不小于它的最小奇数,只需

将该正整数所对应的二进制数的最低位置 1 即可,即用 0x0001 与

该正整数做“按位或”运算。根据上述分析编写的程序如下:

Page 52: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-52

13.3 程序举例#include <stdio.h>

void main()

{ int i;

int a[10]={23,14,24,31,46,55,33,68,27,40};

for(i=0;i<10;i++)

printf("%5d",a[i]);

printf("\n");

for(i=0;i<10;i++)

a[i]=a[i]|0x0001; /* 将正整数转换为不小于它的最小奇数 */

for(i=0;i<10;i++)

printf("%5d",a[i]);

printf("\n");

}

程序运行结果:23 14 24 31 46 55 33 68 27 4023 15 25 31 47 55 33 69 27 41

Page 53: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-53

本 章 小 结 本章介绍了 C 语言中的各种位运算以及由这些运算符和相应操作构成的表达式的计算规则。位运算是进行二进制位的运算,在系统软件中,常处理二进制的问题,因此熟练掌握各种位运算的功能对编写可读性强的程序有很大的优越性。需要注意的是位运算只能用于整数类型的数据。对于位段读者了解其含义即可。主要表现在以下几点: ( 1 )位运算是C语言的一种特殊运算功能,它是以二进制位为单位进行运算的。位运算符只有逻辑运算和移位运算两类。位运算符可以与赋值符一起组成复合赋值符。如 &= , |= , ^= , >>= , <

<=

等。

Page 54: 第 13 章 位运算

普通高等教育“十一五”国家级规划教材

54-54

本 章 小 结 ( 2 )利用位运算可以完成汇编语言的某些功能,如置位,位

清零,移位等。还可进行数据的压缩存储和并行运算。 ( 3 )位段在本质上也是结构类型,不过它的成员按二进制位分配内存。其定义、说明及使用的方法都与结构相同。 ( 4 )位段提供了一种手段,使得可在高级语言中实现数据的压缩,节省了存储空间,同时也提高了程序的效率。