c语言位运算 乘法,C语言 位运算.ppt

本文详细解析了C语言中的位运算符,包括按位与、异或、求反、左移和右移,以及如何通过位运算实现数据压缩和高效编程。通过实际案例演示了如何使用位运算进行数据处理和控制。同时介绍了位段的概念,以及如何在结构体中高效利用位域进行内存管理。
摘要由CSDN通过智能技术生成

《C语言 位运算.ppt》由会员分享,可在线阅读,更多相关《C语言 位运算.ppt(49页珍藏版)》请在人人文库网上搜索。

1、第十一章 位运算,基本内容,11.1 位运算和位运算符 11.2 位段(选讲),基本要求,掌握位运算的操作方法和概念。 掌握位运算符和表达式。 掌握位运算的作用,能够利用位运算进行一些简单的编程。,本章重点,重点:位运算符和表达式。 难点:位段。,本章作业,11.1 位运算符,语言提供了两类、六种位运算符:, c=a ,11.1 位运算符,按位或运算符(|),1. 运算规则: 0|0=0 1|0=1 0|1=1 1|1=1 只要对应位上的值其中一个为1则该位上的结果值为1。 2. 特殊作用: 常用于将一个数的某些特定位置为1 方法:将本数与某个特定数按位或运算即可。,【例11.2】 main(。

2、) int a=9,b=5,c; c=a|b; printf(a=%dnb=%dnc=%dn,a,b,c); ,11.1 位运算符,按位异或运算符(),1. 运算规则: 00=0 10=1 01=1 11=0 只要对应位上的值互不相同则该位上的结果值为1。 2. 特殊作用: 使某些特定位翻转。 任何数与0相异或结果保留原数本身。 交换两个变量的值不用中间变量。 a=ab; b=ba; a=ab; 注意给变量赋值的先后顺序。,【例11.3】 main() int a=9; a=a5; printf(a=%dn,a); ,11.1 位运算符,按位求反运算符(),1. 运算规则: 0=1 1=0 对。

3、每个上的值按位求反:1变为0;0变为1。 例如9的运算为: (0000000000001001)结果为: 1111111111110110,11.1 位运算符,按位求反运算符(),注意:运算符比算术运算、关系运算、逻辑运算和其它运算的优先级别都高。 例如: a&b 先进行a运算,然后进行&运算。,11.1 位运算符,左位移运算符(),1. 运算规则: a=an 将a中所有位向左移动n位 2. 运算的作用: 相当于乘法运算。左移一位相当于乘以2。 高位左边位左移后溢出被舍弃,不起作用。低位补以0。,11.1 位运算符,左位移运算符(),【注意】,11.1 位运算符,右位移运算符(),1. 运算规。

4、则: a=an 将a中所有位向右移动n位。 2. 运算的作用 相当于除法运算。右移一位相当于除以2。,11.1 位运算符,右位移运算符(),【注意】注意数的符号问题即正负的问题。 对于无符号数正数右移时高位补以0。 对于有符号数,高位为0正数右移时高位补以0。 对于有符号数,高位为1负数时: 右移时高位补以0,称之为“逻辑位移”。 右移时高位补以1,称之为“算术位移”。 TC采用“算术位移”,高位补以1。,11.1 位运算符,位运算赋值运算符,位运算符与赋值运算符可以组成复合赋值运算符如: &=, |=, =, =, = 例如: a & = b 相当于:a = a & b a =2 相当于:a。

5、 = a 2,11.1 位运算符,不同长度的数据进行位运算,如果两个数据长度不同(例如long型和int型)进行位运算时(如a & b,而a为long型,b为int型),系统会将二者按右端对齐。 如果b为正数,则左侧16位补满0。若b为负数,左端应补满1。 如果b为无符号整数型,则左侧添满0。,【例11.4】取一个整数a从右端开始的47位。 可以这样考虑: 先使a右移4位,见图。图 (a)是未右移时的情况,图(b) 是右移4位后的情况。目的是使要取出的那几位移到最右端。,右移到右端可以用下面方法实现: a 4, 设置一个低4位全为1,其余全为0的数。可用下面方法实现: ( 0 4 ) 0的全部。

6、二进制为全1,左移4位,这样右端低4位为0。见下面所示: 0:0000000000 0: 1111111111 04:1111110000 (04):0000001111, 将上面二者进行&运算。即 (a 4) & ( 0 4 ) 根据上一节介绍的方法,与低4位为1的数进行&运算,就能将这4位保留下来。,程序如下: main() unsigned a,b,c,d; scanf(%o,&a); b=a4; c=(04); d=b&c; printf(%o, %dn%o, %dn,a,a,d,d); ,运行情况如下: 331 331, 217(a的值) 15, 13 (d的值) 输入a的值为八进制。

7、数331, 即十进制数217, 其二进制形式为11011001。经运算最后得到的d为00001101,即八进制数15,十进制数13。,如果任意指定从右面第m位开始取其右面n位。 只需将程序中的“b=a4”改成“b=a(m-n+1)”以及将“c=(04)”改成“c=(0n)”即可。,【例11.5】循环移位。要求将a进行右循环移位n位,见图。,即将a中原来左面(16-n)位右移n位,原来右端n位移到最左面n位。假设用两个字节存放一个整数。,为实现以上目的可以用以下步骤: 将a的右端n位先放到b中的高n位中。可以用下面语句实现: b=a(16-n); 将a右移n位,其左面高位n位补0。可以用下面语句。

8、实现: c=an; 将c与b进行按位或运算。即 c=c|b;,程序如下: main ( ) unsigned a,b,c; int n; scanf(a=%o,n=%d,&a,&n); b=a(16-n); c=an; c=c|b; printf(%on%o,a,c); ,运行情况如下: a=157653,n=3 157653 75765 运行开始时输入八进制数157653,即二进制数1101111110101011,循环右移3位后得二进制数0111101111110101,即八进制数75765。 同样可以左循环位移。,11.2 位段,以前曾介绍过对内存中信息的存取一般以字节为单位。实际上,有。

9、时存储一个信息不必用一个或多个字节,例如,“真”或“假”用0或1表示,只需1位即可。在计算机用于过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进位,常常在一个字节中放几个信息。那么,怎样向一个字节中的一个或几个二进位赋值和改变它的值呢?,11.2 位段,可以用以下两种方法: (1) 可以人为地在一个字节data中设几项。 例如:a、b、c、d分别占2位、6位、4位、4位(见图)。,如果想将c的值变为12(设c原来为0),可以这样: 将数12左移4位,使1100成为右面起第47位。 将data与“124” 进行“按位或” 运算,即可使c的值变成12。 如果c的原值不。

10、为0,应先使之为0。可以用下面方法: data=data & 0177417,0177417的二进制表示为: 11 11111 1 0000 1111 a b c d 也就是使第47位全为0,其他位全为1。它与data进行 &运算,使第47位为0,其余各位保留data的原状。这个177417称为“屏蔽字”,即把c以外的信息屏蔽起来,不受影响,只使c改变为0。,但要找出和记住177417这个数比较麻烦。 可以用data=data 15是c的最大值,c共占4位,最大值为1111即15。154是将1111移到47位。 再取反,就使47位变成0,其余位全是1。即 15:0000000000001111。

11、 15 4:0000000011110000 ( 15 4 ):1111111100001111 这样可以实现对c清0,而不必计算屏蔽码。,将上面几步结合起来,可以得到 data=data n为应赋给c的值(例如12)。n & 15的作用是只取n的右端4位的值,其余各位置0,即把n放到最后4位上,( n & 15 ) 4, 就是将n置在47位上。见下面:,赋予47位为0,data & (154): 11011011|0000|1010 (n & 15)4: 00000000|1100|0000 (按位或运算) 11011011|1100|1010 可见,data的其他位保留原状未改变,而第47。

12、位改变为12(即1100)了。 但是用以上办法给一个字节中某几位赋值太麻烦了。可以用下面介绍的位段结构体的方法。,(2) 位段 C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域” ( bit field) 。利用位段能够用较少的位数存储数据。,例如: structpacked-data unsigneda2; unsignedb6; unsignedc4; unsignedd4; inti; data; 其中a、b、c、d分别占2位、6位、4位、4位。i为整型。共占4个字节。,也可以使各个位段不恰好占满一个字节。如: structpacke。

13、d-data unsigneda2; unsignedb3; unsignedc4; inti; ; structpacked-datadata;,其中a、b、c共占9位,占1个字节多,不到2个字节。它的后面为int型,占2个字节。在a、b、c之后7位空间闲置不用,i从另一字节开头起存放。,注意,在存储单元中位段的空间分配方向,因机器而异。在微机使用的C系统中,一般是由右到左进行分配的,如图。但用户可以不必过问这种细节。,对位段中的数据引用的方法。如: data.a=2; data.b=7; data.c=9; 注意位段允许的最大值范围。 如果写dataa=8;就错了。因为data.a只占2位。

14、,最大值为3。在此情况下,自动取赋予它的数的低位。例如,8的二进制数形式为1000,而dataa只有2位,取1000的低2位,故dataa得值0。,关于位段的定义和引用,有几点要说明: 位段成员的类型必须指定为unsigned或int类型。 若某一位段要从另一个字开始存放。可以用以下形式定义: unsigneda1; unsignedb2; 一个存储单元 unsigned0; unsignedc3; (另一存储单元),由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。,一个位段必须存储在同一存储单元中,不能跨两个单元。如果第一个单元空间不能容纳下一个位段,则该空间不用,而从。

15、下一个单元起存放该位段。 可以定义无名字段。如: unsigneda1; unsigned 2;(这两位空间不用) unsigned b3; unsigned c4; 在a后面的是无名位段,该空间不用。,位段的长度不能大于存储单元的长度,也不能定义位段数组。 位段可以用整型格式符输出。如: printf(%d,%d,%d, data.a, data.b, data.c); 当然,也可以用%u、%o、%x等格式符输出。 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。如: data.a+5/data.b,本章小结,位运算是语言的一种特殊运算功能,它是以二进制位为单位进行运算的。位运算符只有逻辑运算和移位运算两类。位运算符可以与赋值符一起组成复合赋值符。如&=,|=,=,=,=等。 利用位运算可以完成汇编语言的某些功能,如置位,位清零,移位等。还可进行数据的压缩存储和并行运算。,本章小结,位域在本质上也是结构类型,不过它的成员按二进制位分配内存。其定义、说明及使用的方式都与结构相同。 位域提供了一种手段,使得可在高级语言中实现数据的压缩,节省了存储空间,同时也提高了程序的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值