bool与非布尔运算符的行为

时间:2009-08-18 16:59:02

标签: c++ coding-style standards-compliance

我真正想要的是一个|| =运算符。

old_value = old_value || possible_new_value;
old_value ||= possible_new_value;

第二行是编译器错误(c ++没有|| =运算符)。

那么我的其他选择是什么?

old_value += possible_new_value;
old_value |= possible_new_value;

当我谈到这个问题时,bool如何与其他非布尔运算符一起运行?

-
-=
&
&=
...

我可以凭经验验证这些,但我最感兴趣的是标准所说的内容。

8 个答案:

答案 0 :(得分:12)

根据4.7(积分转换)第4段,“如果目的地类型为bool,请参阅4.12。如果源类型为bool,则值false将转换为零,值true转换为一。“在4.12中,“算术,枚举,指针或指向成员类型的指针的右值可以转换为类型bool的右值。零值,空指针值或空成员指针值转换为{{ 1}};任何其他值都转换为false。“

在不允许true个操作数但是整数操作数的情况下,bool将转换为整数类型。当整数结果存储在bool变量中时,它将转换为bool

因此,您可以使用+和*作为布尔值或和,并且您可以使用|和&也。你不能把它们混合起来,如(bool1 + bool2)&如果所有三个变量都是bool,bool3将产生false。 ((1 + 1)& 1是2& 1,它是0或假。)

记住|和||即使在这里,也不要完全相同。 |将评估双方,然后评估按位或。 ||将评估第一个操作数,然后只有当它为假时才会评估第二个操作数。

我不打算在这里讨论风格问题,但如果我做了类似的事情,我一定会发表评论,以便人们知道我在做什么以及为什么。

答案 1 :(得分:4)

标准说:

4.5-4“整体促销”

  

bool类型的右值可以是   转换为int类型的右值,   错误变为零和真实   成为一个。

5.17-7“分配运营商”

  

表达式的行为   形式E1 op = E2相当于E1 =   E1 op E2除了评估E1之外   只有一次。在+ =和 - =中,E1应该   要么是算术类型要么是a   指向可能是cvqualified的指针   完全定义的对象类型。在所有   其他情况下,E1应具有算术运算   类型。

4.12-1“布尔转化”

  

算术,枚举的右值,   指针或指向成员类型的指针可以   转换为类型的右值   布尔。零值,空指针   value或null成员指针值是   转换为假;任何其他价值   转换为真。

所以这意味着

b1 += b2

其中b1和b2是布尔值,相当于

b1 = b1 + b2

b1和b2将被提升为0/1整数,然后根据0以外的任何值为真的规则转换回布尔值。

所以真值表是

            true   false
true     true   true
false    true   false

所以+ =确实按照标准工作为|| =。但是,这可能会让其他程序员感到困惑,所以我会避免它。

答案 2 :(得分:1)

你能使用三元运算符吗?

  

old_value = !old_value ? possible_new_value : old_value;

答案 3 :(得分:0)

不要将|=&=与bool一起使用。他们大部分时间都可以工作,但这仍然是错误的。通常bool类型只是一个美化的int或char。在我使用的旧代码中,BOOL只是对int或char的类型定义。在这些情况下,如果某些位被操纵,您可能会得到错误的答案(例如,1&2为0(false))。而且我不确定,但我认为按位运算符的结果将是一个整数,即使对于bools也是如此。

答案 4 :(得分:0)

if (!old_value)
    old_value = possible_new_value;

这是原始条件的直接等价物。它可能会生成更简单的代码,因为它不会总是分配给old_value - 但我不希望性能差异在大型程序中很容易测量。

答案 5 :(得分:0)

一个不同之处在于,||等逻辑运算符保证了评估的顺序并提供了短路,而逐位运算符和算术运算符则没有。

我相信编译器会通过将bool转换为应用运算符并转换回来的数值(0,1)来处理非逻辑运算符。这些转换由标准严格定义,例如:

  

算术,枚举,指针或指向成员类型的指针的右值可以转换为bool类型的右值。零值,空指针值或空成员指针值将转换为false,任何其他值都将转换为true。

答案 6 :(得分:0)

讨厌的宏hackery:

#define UPDATE(x) x = x

UPDATE(old_value) || possible_new_value;

但我根本不推荐这个。出于几个原因,像这样的宏是一个非常糟糕的主意。

更理智的功能,但没有短路:

bool set_or(bool &old, bool value) {
  return (old = old || value);
}

...

bool v = false;
set_or(v, true);

答案 7 :(得分:0)

我相信标准明确地将true和false定义为1和0,因此您可以安全地在bool值上使用按位运算符。其他可能在另一个上下文中被隐式视为bool的类型应该被明确转换,以使其可靠地工作。

我看到微软的编译器每次都会生成一个丑陋的警告,因为它认为将int结果隐式转换回bool存在危险。