为什么〜(真的是真的)不是真的吗?布尔运算符(否定)适用于`unsigned char`s,但不适用于bools? (C ++)

时间:2014-05-18 21:22:47

标签: c++ boolean boolean-expression boolean-operations

我经常听到"一切"除了0是真的。但是现在我发生了很奇怪的事情......或者我只是觉得我不是以正确的方式做到这一点。以下是发生的事情:

当我想检查 a 是否等同于 b 时,我可以使用NOT(a XOR b)。当我检查unsigned char时,一切正常,例如

unsigned char a = 5;
unsigned char b = 3;
unsigned char c = ~(a^b);

给了我c == 249

a 是:00000101,即5。

b 是:00000011,即3。

〜(a ^ b)是:11111001,即249。

现在,让我们试试bool

cout << ~(true^true) << ~(true^false) << ~(false^true) << ~(false^false) << endl;
cout << ~(~(true^true)) << ~(~(true^false)) << ~(~(false^true)) << ~(~(false^false)) << endl;

if (~(true^true) == true)
    cout << "true";
else
    cout << "false";

这让我在控制台中:

-1-2-2-1
0110
false

虽然我预计第一行是:

1001

在问朋友后,他建议我尝试!而不是~,看看它是否能正常运作。并且(我认为)它现在正常工作。但我不明白为什么。不应该布尔否定对bool工作吗?

5 个答案:

答案 0 :(得分:9)

您误解了算术转换。当您对整数类型的某个表达式~ee时,该值首先会提升为至少 - int,并且e1 ^ e2的值相同(对于任何算术表达式) , 对于这个问题)。因此,true ^ true首先将其操作数提升为int,产生1 ^ 1,确实为0,因此您最终得到~0,在您的平台上{{1} }}

通过将结果转换回-1

,您可以模糊地理解您的操作
bool

在你的最后一个问题中,由于你有一个带有std::cout << static_cast<bool>(~(true ^ true)) 运算符的表达式,其中两个操作数具有不同的类型,所以两个操作数都被提升为公共类型,这又是==和{{ 1}}与int不同。同样,您可以先将两个操作数转换为-1,以获得所需的相等性。


元课程是C ++中作用于整数的内置运算符实际上仅在1上运行且更宽,但不在任何较短类型上运行(boolintbool)(和类似的考虑适用于通过省略号传递整数)。虽然这有时会引起一些混乱,但我想这也会简化语言规则。这是C ++ C传承的一部分。

答案 1 :(得分:4)

  

我经常听到&#34;一切&#34;除了0是真的

它对条件有效,例如在if语句中(这里和下面我引用了C ++标准)

  

作为表达式的条件的值是的值   表达式,上下文转换为bool以外的语句   开关

例如,如果您要写为

if (~(true^true) )
    cout << "true";
else
    cout << "false";

代替您的代码段

if (~(true^true) == true)
    cout << "true";
else
    cout << "false";

或使用逻辑否定运算符!

  

9逻辑否定运算符的操作数!在语境上   转换为布尔(第4条);如果转换它的值是真的   操作数是假的,否则是假的。结果的类型是bool

至于运营商==那么

  

6如果两个操作数都是算术或枚举类型,则通常   对两个操作数执行算术转换;每一个   如果指定的关系为真,则运算符应为真   如果是假的,则为false。

就是

if (~(true^true) == true)

应用通常的算术转换,即布尔值true转换为整数值1并且它不等于左operanf的表达式,因为左操作数的内部二进制表示不同于1,如第一个输出所示代码段..

答案 2 :(得分:3)

仅考虑您的第一个例子,

~(true^true)

首先,^的操作数被提升为int,因此这相当于

~(1^1)

然后xor为1本身产生一个全零位模式,无论int表示如何表示值0:

~0

这将全零比特模式中的每个比特反转为0,从而产生具有所有比特1的比特模式,例如,对于32位int

int( 0xFFFFFFFF )

现在几乎是通用的二元补码形式表示有符号整数,这就是值-1。

因此您的输出

-1

答案 3 :(得分:2)

~有点不明白。

e.g。对于unsigned char,~0是255,而对于@!true,则为〜!{/ p>

答案 4 :(得分:2)

逻辑否定和按位否定之间存在差异。按位否定翻转变量中的位,逻辑否定翻转逻辑值,即true / false。考虑例如数字5,以二进制表示为101.如果只翻转位(~5),则会得到11111010,这不是假的,因为在c ++中只有全零为假。但是如果你计算(!5)你会得到全零,这将在一个条件下工作。