文档介绍:第12章位运算
位运算符及其应用
位段及其应用
C语言中提供了如下6种的位运算符:
& 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移
~ 按位取反
提示:只允许对整型、字符型数据进行位运算,而实型数据不能进行位运算。
位运算规则:
若 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)"按位与"运算经常用于将某些二进制位屏蔽掉。
编写函数:使一个整数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。
:将一个字节的高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)按位异或运算经常用与将某些位翻转。
编程实现,将一整数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 。
若定义: int a=8; 即a= 0000 1000 , 则语句a=a<<2;
将 a 的各二进制位左移 2 位,空出的低位补0。结果为:0010 0000
右移:将一个数的各个二进制位右移若个位,低位右移后舍弃,高位补 0还是补1,要区别有符号数还是无符号数:无符号数高位补0,有符号数高位补原符号位。
若定义 unsigned int a=8; 即 00001000,
则语句 a=a>>2 ;将 a 的各二进制位右移 2 位,空出的高位补 0。结果为: 0000 0010
位段
1.  位段的概念
以位为单位定义其长度的结构体成员。
,分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 的存储结构如图:
a b c i ……成员名
2 6 4 4 16 ……长度
位段是结构体类型的某个成员,因此,位段的引用同结构体成员的引用方法相同。
如:=0x01; /*给位段a赋值, */
=0x0a; /*给位段b赋值*/
=12; /*给位段 i赋值*/
printf(“%02x, %02x, %4d”, , , ); 输出: 01,