2011-02-23 22 views
2

下面是一个代码段有趣的事情!在布尔值操作

#define T 0xFF 
using namespace std; 
int main(void) { 
    char c = T; 
    bool *pc = (bool *)(&c); 
    bool nc = !(*pc); 
    cout << "print: " << hex << nc << endl; 

    nc = T; 
    cout << "print: " << hex << nc << endl; 

    nc = c; 
    cout << "print: " << hex << nc << endl; 
} 

结果是

print: fe 
print: 1 
print: 1 

如果类型使用值0xFF的投一个char到一个bool,布尔值是1

但是,当输入一个char指针指向一个bool指针时,0xFF变成0xFE,只有最后一位被翻转了!操作。

似乎gcc认为bool是0或1,如果bool对象的构造函数没有被调用,它只会将内存解释为包含一个bool并将最低有效位翻转。

但是当bool被char设置时,它是否会触发复制构造器?但为什么不同?

+0

@Charles感谢您修复凌乱的代码输出。 – 2011-02-23 08:16:56

回答

8

A bool只能取值truefalse

当您执行!(*pc)你得到未定义行为因为你告诉一个bool对象执行!时实际上pc在一个char对象指向的编译器。 (这是从char*的C风格的转换,以bool*那是危险的,即使未定义行为只有当你申请的!操作发生。)

当转换charint(如0xFF)到bool将所有非零值转换为true,并将零值转换为false。

+0

为了清楚起见,它是从char *到bool *的转换导致了未定义的行为。与逻辑否定运算符无关。 – qbert220 2011-02-23 08:47:09

+1

@ qbert220:不,您可以投射指针值而不会导致UB。该标准规定,如果你退回到原始类型,那么你必须返回原始值(在这种情况下c样式转换将与'reinterpret_cast'相同),所以指针转换本身不会导致UB,尽管它是'危险'或'不安全'。这是使用UB的指针转换结果的行为,因为它没有指定转换的值是什么。直观地说,它实际上不能指向正确类型的对象。 – 2011-02-23 09:44:56

+1

@ qbert220:我承认,有一种说法认为一元'*'操作符本身会导致UB,但是有强有力的论据表明,仅仅为无效对象形成_lvalue_并不一定会导致UB。例如,使用'&array [size]'形成超出数组末尾的指针通常被认为是有效的,因为对象'&array [size]'实际上并未被“使用”。无论哪种方式,指针转换绝对不会导致UB,但'!'肯定会(因为它读取无效对象的值),如果'*'还没有导致UB。 – 2011-02-23 09:52:03