c语言程序设计的位运算,C语言程序设计位运算.ppt

1 C语言允许对内存中的字节或字节内的二进制位进行运算, 即位运算. 12.1 位运算符和位运算 位运算符共6 种: a = a ^ b ; b = b ^ a ; a = a ^ b ; printf ( “ %d , %d ” ,a , b ) ; } 输出: 4 , 3 0000001100000000 0000010000000000 0000011100000000 a b a 0000001100000000 b 0000010000000000 a 12.1.3 “按位异或”运算符(^) 作用: 对参加运算的两个二进制数按位进行逻辑异或运算. 规则: 0^0 = 0, 1^0 = 1, 0^1 = 1, 1^1 = 0 结论: 利用异或运算,不必设置第三个变量就可以实现两个 整型变量值的交换。 6 用途:某位“异或”1 要变,某位“异或”0 不变。 1) 使指定位翻转。比如:要使一个字节的低四位翻转,只需异 或0x0f 。 00100011 a 00001111 a 0x0f 00101100 2) 清零。一个整型(含字符型)数据“异或”自身,便清零. 00100011 a a 00000000 00100011 a 7 12.1.4 “按位取反” 运算符(~) 作用: 对一个二进制数按位取反,是一个单目运算符. 如: a = 15 则 ~ a = 65520 00000000 00001111 11111111 11110000 a ~ a 注意: ~ 和! 运算符是两个完全不同的运算符。~ 的优先级与 + +,  , !相同,且结合性都是从右至左。 例如:main ( ) { int a = 0 , b = 1 ; printf ( “ %d , %d \n”, ~a ,~b ) ; printf ( “ %d , %d \n”, !a , !b ) ; } 运行结果: 1, 2 1, 0 0000000000000000 1111111111111111 0 ~ 0 8 应用举例: 若有一个整数a ,想使它最低一位为0(即屏蔽 d0位),而其它位不变。请问如何操作? 方法是: a=a 请问可用 a=a 吗? 答:对于以16位存放一个整型数据的计算机系统,后者也是 可以的。但对于以32位(或更多位)存放一个整型数据的系 统(如VAX 11/780),后者是不可以的。因此,后者的可移植 性很差;而前者则适合于任何系统,程序的可移植性好! 0000101100000000 1111111011111111 a 0xfffe 0000101100000000 1111111011111111 0000001000000000 0000000000000000 a 0xfffe 11111110111111111111111111111111~1 16位整型32位整型 9 12.1.5 左移位运算 () 作用: 将操作数的各个二进位顺序右移.左端空出的位补0 或补1, 而移出右端的位则被舍去. 如: an 表示将a 的各个二进位顺序右移n 位. 说明: 右移运算的结果与操作数的符号有关. 就Turbo C2.0而言: 1) 无符号数为“逻辑右移”,即左端空出位一律补0 . 2) 有符号数为“算术右移”,即正数右移,空位补0 ,负数右移 ,空位补1 .一句话,算术右移是指最高位移入符号位。 其它系统对有符号数可能依然采用“逻辑右移”,这随系统而定 . 0000000010000000 0000000001000000 0000000011000000 a a 1 a 1 逻辑右移,结果为 16384 算术右移,结果为 16384 算术右移运算相当于除2 运算。 右移 1 位,相当于除以2 。 右移n 位,则除以2n 。 例如: a = 32768 12 12.1.7 位运算符的优先级与结合性 ~ c = ~ ( ~ 0 m; c = ~ ( ~ 0 n 00011011 11110101c 01111011 11110101c 16 main ( ) { unsignde a , b , c ; int n ; scanf ( “ %o , %d ” , b = a n ; c = c | b ; printf ( “ %o \n %o \n” , a , c ) ; } 如输入: 157653 , 3  输出为: 157653 75765 同样的方法,可以实现循环左移。 11011111 10101011 01111011 11110101 a c 17 12.3 位 段 以前,我们内存的存取都是以字节为单位,即信息存储至 少要占用一个字节。实际上,有时存储一个信息不必占用一个 或多个字节,而只需占用1位或几位便可。这在计算机过程控 制和数据通信领域经常会遇到。C语言提供对这方面的处理, 而且可用以下两种方法实现: 1、通过位运算实现对1位或几位的操作:比如我们可以人为 地将一个字节data划分为几项,假如是四项a、b、c、d, 且它们分别占1位、3位、2位、2位(如下图所示)。如果 欲将b的值变为6,则可以这样: data ab cd 70 18 (1)将b项(4 – 6位)清零 data = data 或者 data = data (3)将data与“64”进行按位或运算,即可实现将b的值变为6 。 10001111 70 (2)将数6左移4位,使110成为4 - 6位 01100000 70 x000xxxxx110xxxx data data |(64 ) ~(74 ) 说明:其中(1)步中的0x8f,称为“屏蔽字”,即把data中b的 信息屏蔽掉,而其它信息不受影响。 19 2、通过位段来实现对1位或几位的操作:C语言允许在一个结构体中 以位为单位来指定其成员所占内存的长度,这种以位为单位的成 员称为“位段”(或“位域”bit field)。例如: Struct packed_data { unsigned a:2; unsigned b:6; unsigned c:4; unsigned d:4; int i; }data; Struct packed_data { unsigned a:2; unsigned b:3; unsigned c:4; int i; }; Struct packed_data data; abcd i 164462 abc 空闲 i 167432 70152331 20 关于位段的定义和引用的说明: 1)位段成员的类型必须指定为unsigned int型。 2)若某一位段要从另一存储单元(字)单独开始存放,应这样定义 : Struct packed_data { unsigned a:1; unsigned b:2; unsigned :0; unsigned c:3; /* 在Turbo C中表示c从第3个字节开始存放 */ }; 3)可以定义无名字段,如: Struct packed_data { unsigned a:1; unsigned :2; /* 表示这两位空间不用 */ unsigned b:3; unsigned c:4; }; 21 4) 一个位段必须存储在同一存储单元(字)中,不能跨越两个单 元。如果第一个字不能容纳下一个位段,则该空间不用,而 从下一个字开始存放。比如: Struct packed_data { unsigned a:5; unsigned b:6; unsigned c:6; int i; }; Struct packed_data data; i空闲d空闲ba 166565 注意:上面定义的结构体共占6个字节(3个字)。 150 10 015 22 5) 位段的长度不能大于存储单元(字)的长度,也不能定义 位段数组。 6) 位段可以用整型格式符(%d,%u,%o,%x)进行输出。如: printf(“%d,%d,%d”,data.a,data.b,data.c); 7) 位段可以在数值表达式中引用,它会被系统自动地转换成 整型数据来处理。如: data.a + 5/data.b 是合法的。

展开阅读全文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值