〜操作员扼杀bool

时间:2012-06-28 13:20:52

标签: c++ boolean

按位补码运算符为bool操作数做了意想不到的事情。下面的程序产生了这个输出:

x: 123456fe   ~x: 87654301   !x: 556677ff
x: 123456ff   ~x: 87654301   !x: 556677fe

对于X中的任何字节值,~X似乎总是用01覆盖整个字节。 然而,X似乎只补充了字节的LSB ......

我想这是有意义的,如果将bool转换为int,应用按位补码,并将结果转换回bool。 BUT ,我不明白为什么一个结果会将8位写入内存而另一个只写1位。

#include "stdio.h"

typedef union {
    bool b;
    unsigned int i;
} ib_T; 

int main(int argc, char **argv) {
    ib_T x, y, z;

    x.i = 0x123456fe;
    y.i = 0x876543ff;
    z.i = 0x55667777;

    y.b = ~x.b;
    z.b = !x.b;
    printf("x: %08x   ~x: %08x   !x: %08x\n", x.i, y.i, z.i);

    x.i = 0x123456ff;
    y.b = ~x.b;
    z.b = !x.b;
    printf("x: %08x   ~x: %08x   !x: %08x\n", x.i, y.i, z.i);
}

1 个答案:

答案 0 :(得分:6)

从您之前未分配的联盟成员中读取未定义的行为。

  

在联合中,最多一个非静态数据成员可以随时处于活动状态,也就是说,任何时候最多一个非静态数据成员的值都可以存储在一个联合中。

当类型共享一个公共布局时,此规则有一个例外,这在您的情况下不适用。通常,如果您分配到x.i,那么您只能从x.i阅读;如果您想从x.b开始阅读,则需要先分配到x.b

  

我想这是有道理的,如果将bool转换为int,应用了按位补码,并将结果转换回bool。

这是100%正确:下面的代码段

bool b;
b = false;
printf("b: %d\n", b);
b = ~b;
printf("~b: %d\n", b);
b = ~b;
printf("~~b: %d\n", b);

打印

b: 0
~b: 1
~~b: 1

bool被提升为int,应用了波浪号~,然后使用通常的“零/非零”规则将结果转换回bool