右移运算符>>
右移运算符是a>>2表示将a的各二进制位右移2位,移到右端的低位被舍弃,对无符号数,高位补0。
例如a=017时,a的值用二进制形式表示为00001111, 舍弃低2位11,得到a >> 2 == 00000011。
可以得到:
右移一位相当于除以2,右移n位相当于除以2n。
有关符号位的注意事项如下:
对无符号数,右移时左边高位移入0;
对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0;
如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统,有的系统移入0,有的系统移入1。
移入0的称为逻辑右移, 即简单右移;
移入1的称为算术右移。
例如,a的值是十进制数-2:
a = 1111 1110(用二进制形式表示);
无符号数:a>>1 = 0111 1111 (逻辑右移时);
有符号数:a>>1 = 1111 1111 (算术右移时)。
练习如下:
#include <stdio.h> int main(){ unsigned char a = -2; char b = -2; a = a >> 1; b = b >> 1; printf("a = %d\nb = %d\n", a, b); return 0; }
打印:
a = 127 b = -1
显然,C语言对于有符号数和无符号数的处理是不同的。
位运算赋值运算符
位运算符与赋值运算符可以组成复合赋值运算符。
例如: &=、|=、>>=、<<=、^=。
所以,a &= b
相当于a = a & b
,a <<= 2
相当于a = a << 2
。
二、位运算举例
练习:
取一个字符型变量a从右端开始的2-5位。
实现思路:
(1)先使a右移2位a >> 2,目的是使要取出的那几位移到最右端;
(2)设置一个低4位全为1,其余全为0的数,即~(~0 << 4);
(3)将(1)、(2)进行&运算,(a >> 2) & ~(~0 << 4)。
代码如下:
#include <stdio.h> int main(){ char a, b, c, d; printf("Please input the number:\n"); scanf("%d", &a); b = a >> 2; c = ~(~0<<4); d = b & c; printf("%d\n"); return 0; }
打印:
Please input the number: 37 9
练习:
要求将a进行右循环移位,如下:
代码如下:
#include <stdio.h> int main(){ unsigned a, b, c, d; int n; printf("Please input the number:\n"); scanf("%d", &a); printf("Please enter the number of digits to be moved:\n"); scanf("%d", &n); b = a << (sizeof(char) * 8 - n); c = a >> n; d = b | c; printf("result = %d\n", d); return 0; }
打印:
Please input the number: 25 Please enter the number of digits to be moved: 2 result = 1606
三、位段
信息的存取一般以字节为单位,但有时存储一个信息不必用一个或多个字节。
例如,真或假用0或1表示,只需1位即可。
在计算机用于过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,常常在一个字节中放几个信息。
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为位段或称位域(bit field),利用位段能够用较少的位数存储数据。
如下:
struct packed_data{ unsigned a:2; unsigned b:6; unsigned c:4; unsigned d:4; int 1; } data;
位段的定义和引用的说明:
(1)位段成员的类型必须指定为unsigned或int类型。
(2)若某一位段要从另一个字开始存放,可用以下形式定义:
unsigned a:1; unsigned b:2; // 一个存储单元 unsigned :0; unsigned c:3; // 另一存储单元
a、b、c应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将a、b存储在一个存储单元中,c另存在下一个单元(存储单元可能是一个字节,也可能是2个字节,视不同的编译系统而异)。
(3) 一个位段必须存储在同一存储单元中,不能跨两个单元;
如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。
(4) 可以定义无名位段。
(5) 位段的长度不能大于存储单元的长度,也不能定义位段数组。
(6) 位段可以用整型格式符输出。
(7) 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。