按位逻辑运算符

  按位逻辑运算符&,|,^,~,>> 和 >> 可以应用于整型和枚举---也就是说,应用于bool、char、short、int、long,它们的无符号形式,以及enum。这时将执行常规的算术转换(C.6.3节)以确定结果类型。

  按位运算符的典型用途是实现很小的集合概念(位向量)。这时,人们采用无符号整数的每个位表示集合的一个元素,位的个数是集合成员数的上限。二进制运算 & 解释为求交,| 作为求并,^ 作为对称差,~ 作为求补。可以利用枚举作为这样一个集合的成员命名。下面是从ostream的某个实现中取来的一个例子:

    enum ios_base::iostate {
        goodbit=0, eofbit=1, failbit=2, badbit=4
    };

流的实现可以设置和检测它的状态,比如,

    state = goodbit;
    // ...
    if(state & (badbit|failbit))    // 流有问题

额外的括号是必须的,因为 & 具有比 | 更高的优先级。

  函数的遇到输入的结束时可以采用如下方式报告情况:

   state |= eofbit;

这里的 |= 运算符用于向state添加东西。简单赋值state=eofbit将清除所有其他二进制位。

  从流的外面可以去查看这些流状态标志。例如,我们可以看两个流的状态有什么差异:

    int diff = cin.rdstate()^cout.rdstate();        // rdstate()返回流状态

计算流的差异是很常见的事情,对于其他类似的类型,计算差异也常常是最基本的工作。举例来说,请想一想将一个表示正在被处理的中断集的位向量,与另一个需要去处理的中断集的位向量相比较的问题。

  请注意,这里给出的有关二进制位的琐碎事物是取自iostream的实现,而不是想用在用户界面上。方便的位操作有可能非常重要,但是,为了可靠性、可维护性、可移植性等,还是应该将它保持在系统的底层中。有关集合的更一般概念请看标准库中的set(17.4.3节),bitset(17.5.3节)和vector< bool >(16.3.11节)。

  位域(C.8.1节)也可以用于作为在一个机器字里移位和掩盖,以便抽取一段二进制位的一种方便方式。这些当然都可以通过按位逻辑运算符完成。例如,要抽取32位的long中间的16位,可以如下写:

unsigned short middle(long a) { return (a >> 8) & 0xffff; }

不要将按位逻辑运算符与逻辑运算符&&、||和!搞混了。逻辑运算符总返回true或false,它们主要是用在if、while或者for语句的检测部分(6.3.2节、6.3.3节)。例如,!0(非0)是值true,而~0(0的补)则是一个全1的二进制模式,它在2补码表示中代表-1。

🔚