第12章俊通算
第12章 位运算
1位运算符及其应用 2.位段及其应用
1. 位运算符及其应用 2. 位段及其应用
121位运算符和位运算表达式 ■C语言中提供了如下6种的位运算 &按位与 按位或 按位异或 左移 右移 按位取反 提示:只允许对整型、字符型数据进行位运算,而 实型数据不能进行位运算
12.1位运算符和位运算表达式 ◼ C语言中提供了如下6种的位运算符: & 按位与 | 按位或 ^ 按位异或 > 右移 ~ 按位取反 提示:只允许对整型、字符型数据进行位运算,而 实型数据不能进行位运算
1.位运算规则 A B A&B aB A'B 101 a1100 例12.1若a=(15)10=(00001112, b=(80)10=(010100001 刂:a&b=00000ab=0101111l a^b=0101111 a=11110000
1. 位运算规则: 例12.1 若 a=(15)10=(00001111)2, b=(80)10=(01010000)10 则: a&b = 0000 0000, a|b = 0101 1111, a^b =01011111 , ~a = 1111 0000 A B A&B A|B A^B ~a 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0
1.位运算的应用: 1)"按位与"运算经常用于将某些二进制位屏蔽掉 例122编写函数:使一个整数k中的低4位置0。 分析:用“与”运算实现:将k的低4位与0相与,其 他位与1相与,即将k与十六进制的1110相与 程序如下: unsigned int set(unsigned int k) {k=k&0x110 return(kB) 结论:任何二进制位与0相与能实现置0,与1相与该 位保持不变
1. 位运算的应用: 1)"按位与"运算经常用于将某些二进制位屏蔽掉。 例12.2 编写函数:使一个整数k中的低4位置0。 分析:用“与”运算实现:将k的低4位与0相与,其 他位与1相与,即将 k与十六进制的 1110 相与。 程序如下: unsigned int_set(unsigned int k) { k=k & 0x1110 ; return(k); } 结论:任何二进制位与0相与能实现置0,与1相与该 位保持不变
2)"按位或"运算经常用与将某些二进制位置1 例12.4将一个字节的高4位置为1010并输出结果 分析:直接用位运算符,可以很方便的置1、清0、翻转等,但 无法直接实现置给定的值。可以用两步实现:首先将高4位 清0,然后与10100000或。程序如下 设a为待处理的数据,转换成二进制为00001000, b用来保存将a的高4位清0后的结果 main f unsigned char a,b,c, a=8 b-a&0x0fcb0xa20:c用于保存最终结果/ printi( ox,0); 运行结果:10101000
2)"按位或"运算经常用与将某些二进制位置 1。 例12.4:将一个字节的高4位置为1010并输出结果。 分析:直接用位运算符,可以很方便的置1、清0、翻转等,但 无法直接实现置给定的值。可以用两步实现:首先将高4位 清 0,然后与1010 0000相或。程序如下: /*设 a 为待处理的数据,转换成二进制为00001000, b用来保存将a的高4位清0后的结果*/ main() { unsigned char a,b,c; a=8; b=a&0x0f; c=b|0xa0; /*c用于保存最终结果*/ printf("%x",c); } 运行结果:10101000
3)按位异或运算经常用与将某些位翻转 例12.5编程实现将一整数n的高8位翻转,低8位不变 分析:用“异或”运算实现,即高8位与1相异或,低8位与0 相异或,也就是k与十六进制的f00相异或。程序如下 main( {intn=129; printf(\n before reset, n=%ox,n); n=nAOxff00 printf(\n after reset, n=%ox,n); }运行结果: before reset,n=0000000010000001 after reset.n=1111llll 10000001 结论:任何二进制位与0异或,保持不变;与1异或,对应位 翻转
3)按位异或运算经常用与将某些位翻转。 例12.5 编程实现,将一整数n的高8位翻转,低8位不变 分析:用“异或”运算实现,即高8位与1相异或,低8位与0 相异或,也就是k与十六进制的ff00相异或。程序如下: main() { int n=129; printf("\n before reset,n=%x",n); n=n∧0xff00; printf("\n after reset,n=%x",n); } 运行结果: before reset,n=00000000 10000001 after reset,n=11111111 10000001 结论:任何二进制位与0异或,保持不变;与1异或,对应位 翻转
4)左移、右移运算实现将一个数的各个二进制位向左、向 右移若干位。 左移:将一个数的各个二进制位左移若干位,高位左移 后舍弃,低位补0 若定义:inta=8;即n=00001000,则语句a=a<<2 将a的各二进制位左移2位,空出的低位补0。结果为 00100000 右移:将一个数的各个二进制位右移若个位,低位右移 后舍弃,高位补0还是补1,要区别有符号数还是无符号 数:无符号数高位补0,有符号数高位补原符号位 若定义 unsigned int a=8;即000010 则语句将a的各二进制位右移2位,空出的 高位机0。结果为:00000010
4)左移、右移运算实现将一个数的各个二进制位向左、向 右移若干位。 左移:将一个数的各个二进制位左移若干位,高位左移 后舍弃,低位补0 。 若定义: int a=8; 即a= 0000 1000 , 则语句a=a>2 ;将 a 的各二进制位右移 2 位,空出的 高位补 0。结果为:0000 0010
122位段 1.位段的概念 以位为单位定义其长度的结构体成员 2.位段的定义 例12.6若某个控制字长32位,分5段,每段的长度分别为: 2,6,4,4,16位;每段存放一个信息,且第4段空 出不用。可用如下结构体类型描述 struct con word { unsigned a:2;/位段a,长度为2*/ unsigned b:6;/a,b,c为有名位段* unsigned c: unsigned:4;/该位段为无名位段,表示这4位空间 空出不使用 int i 3 data;
12.2 位段 1. 位段的概念 以位为单位定义其长度的结构体成员。 2.位段的定义 例12.6若某个控制字长32位,分5段,每段的长度分别为: 2 ,6 ,4 ,4 ,16位 ;每段存放一个信息,且第4段空 出不用。可用如下结构体类型描述: struct con_word { unsigned a: 2; /*位段a,长度为2*/ unsigned b: 6 ; /*a,b,c为有名位段*/ unsigned c: 4; unsigned : 4; /*该位段为无名位段,表示这4位空间 空出不使用*/ int i ; } data;
变量data的存储结构如图: 成员名 16 长度 3.位段的引用 位段是结构体类型的某个成员,因此,位段的引用同结构体成 员的引用方法相同。 如:data,a=0x01;/给位段a赋值,* data b=0xOas 给位段b赋值* data.i12; 给位段谶值兴 printf(o02x, %002x, %04d, data,a data, b, data,i ) 输出:01,0a,12 特别提示:使用位段时,要注意该位段的能表示的数据的范围
◼ 变量data 的存储结构如图 : ◼ a b c i …… 成员名 ◼ 2 6 4 4 16 …… 长度 3.位段的引用 位段是结构体类型的某个成员,因此,位段的引用同结构体成 员的引用方法相同。 如:data.a=0x01; /*给位段a赋值,*/ data.b=0x0a; /*给位段b赋值*/ data.i=12; /*给位段 i赋值*/ printf(“%02x, %02x, %4d”, data.a , data.b ,data.i ); 输出: 01, 0a, 12 特别提示:使用位段时,要注意该位段的能表示的数据的范围