一、位运算符和位运算
C语言提供如下表所列出的位运算符:
说明:
(1)位运算符中除~以外,均为二目(元)运算符,即要求两侧各有一个运算量。
(2)运算量只能是整型或字符型的数据,不能为实型数据。
1、“按位与”运算符(&)
参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1, 则该位的结果值为1;否则为0。
按位与有一些特殊的用途:
(1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要找一个二进制数, 来的数中为1的位,新数中相应位为0。然后使二者进行& 其中各个位符合以下条件: 运算,即可达到清零目的。
(2)取一个数中某些指定位。如有一个整数a(2个字节),想要其中的低字节。只需将a与(377)。按位与即可。
(3)要想将哪一位保留下来,就与一个数进行&运算,此数在该位取1。
2、“按位或”运算符(|)
两个相应的二进制位中只要有一个为1,该位的结果值为1。即0|0 = 0,0|1 = 1,1|0 = 1,1|1 =1。
3、“异或”运算符(^)
异或运算符^也称XOR运算符。它的规则是:若参加运算的两个二进制位同号,则
结果为0(假);异号则为1(真)。即0^0=0,0^1=1,1^0=1,1^1=0。
下面举例说明^运算符的应用:
(1)使特定位翻转
(2)与0相^,保留原值
(3)交换两个值,不用临时变量
4、“取反”运算符(~)
~是一个单目(元)运算符,用来对一个二进制数按位取反,即将0变1,将1变0。例 如,~025是对八进制数25(即二进制数00010101)按位求反。
5、左移运算符(<<)
用来将一个数的各二进制位全部左移若干位。 高位左移后溢出,舍弃。
6、右移运算符(>>)
a>>2表示将a的各二进制位右移2位,移到右端的低位被舍弃,对无符号数,高位
补0。
右移一位相当于除以2,右移n位相当于除以2^n。
在右移时,需要注意符号位问题。对无符号数,右移时左边高位移入0;对于有符号 的值,如果原来符号位为0(该数为正),则左边也是移入0,如同上例表示的那样。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。移入0的称为“逻辑右移”,即简单右移;移入1的称为“算术右 移”。
7、位运算赋值运算符
位运算符与赋值运算符可以组成复合赋值运算符,例如: &=,|=,>>=, <<=,^=等。
8、不同长度的数据进行位运算
如果两个数据长度不同(例如long型和int型)进行位运算时(如a &b,而a为long 型,b为int型),系统会将二者按右端对齐。如果b为正数,则左侧16位补满0;若b为负 数,左端应补满1;如果b为无符号整数型,则左侧添满0。
二、位段
以前曾介绍过对内存中信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节。 例如,“真”或“假”用 0或1表示,只需1位即可。
可以用以下两种方法向一个字节中的一个或几个二进制位赋值和改变它的值:
(1)、可以人为地将一个整型变量data分为几部分。
(2)位段
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位 的成员称为“位段”或称“位域”(bit field)。利用位段能够用较少的位数存储数据。
关于位段的定义和引用,有几点要说明:
(1)位段成员的类型必须指定为unsigned或int类型。
(2)若某一位段要从另 个字开始存放,可以用以下 式定义:
unsigned a:1;(一个存储单元) unsigned b:2; (一个存储单元)unsigned :0; unsigned c:3;(另一存储单元)
(3)一个位段必须存储在同一存储单元中,不能跨两个单元。 如果第一个单元空间不能容纳下一个位段则该空间不用,而从下一个单元起存放该位段。
(4)、可以定义无名位段。
大于存储单元的长度,也不能定义 (5)位段的长度不能大于存储单元的长度,也不能定义位段数组。
(6)位段可以用整型格式符输出。
(7)位段可以在数值表达式中引用,它会被系统自动地转换成整型数。例如data.a+5/data.b 是合法的。