掩码是个常量或变量,用于从另一个变量或表达式提取所需要的位。由于int常量1的二进制表达形式如下:
00000000
它可以用于判断一个int表达式的低端位。下面的代码使用了这个掩码,打印出一个0和1交替的序列:
for(i=0;i<10;++i)
如果我们想在一个表达式中找到一个特定位的值,我们可以使用掩码,把这个位置设置为1,其余的位设置为0。例如,我们可以使用表达式1<<2作为第3个位(从右开始计)的掩码。下面这个表达式
(v&(1<<2))?1:0
的值为1或0,取决于v的第3个位。
掩码的另一个例子是常量值255,它的二进制表达形式是:00000000
由于只有最低端的那个字节全为1,所以表达式( v&255
这里我们用bit_print()函数来实现打印int值的二进制形式。这个函数使用掩码来打印int值的位表示形式。源码如下:
#include<limits.h>
void bit_print(int a)
{
int i;
int n=sizeof(int)*CHAR_BIT;
int mask=1<<(n-1);
for(i=1;i<=n;++i)
{
putchar(((a&mask)==0)?'0':'1');
a<<=1;
if(i%CHAR_BIT==0&&I<n)
putchar(' ');
} }
分析:
(1)#include<limits.h>
在ANSI C中,符号常量CHAR_BIT是在limits.h头文件中定义的,大多数系统中其值为8。它表示1个char值的位数,或者1个字节所包含的位数。ANSI规定1个字节至少包含8位。
(2)int mask=1<<(n-1)
由于操作符优先级的关系,在初始化中使用括号并不是必须的。我们加上括号是为了使代码可读性更佳。由于<<的优先级高于=,因此表达式 1<<(n-1)首先进行求值。假设n的值为32。常量1只有最低端的1位为1。表达式1<<31把这个位左移到最高端。因 此,mask除了最高位(符号位)之外的所有位都是0,而符号位为1。
(3)for(i=1;i<=n;++i)
首先考虑下面的表达式:(a&mask)==0
如果a的最高位为0,表达式a&mask的所有位均为0,表达式(a&mask)==0的值为true。反之,如果a的最高位为1,表达式a&mask的最高位为1,(a&mask)==0的值为false。
现在考虑下面这个表达式:((a&mask)==0)?'0':'1'
如果a的最高位为0,这个条件表达式的值为'0',否则它的值为'1'。因此,如果a的最高位为0,putchar()就打印0,否则就打印1。
(4)
在a的最高位被打印出来之后,我们把a的所有位左移1位,并把结果放回到a中。注意:a<<=1; 等价于 a=a<<1
表达式a<<1的值与a的位模式相同,只不过左移了1位。这个表达式本身并没有更改a在内存中的值。与此相反,表达式a<<=1却修改了a在内存中的值。它的效果就是把下一位移动到最高位,以便下一次循环时被打印出来。
(5)
如果我们假定符号常量CHAR_BIT的值为8,这行代码将导致每组8为打印完成之后再打印1个空格。