布尔运算符 ++ 和 --

Posted

技术标签:

【中文标题】布尔运算符 ++ 和 --【英文标题】:bool operator ++ and -- 【发布时间】:2011-03-27 21:32:30 【问题描述】:

今天在编写一些 Visual C++ 代码时,我遇到了一些令我惊讶的事情。似乎 C++ 支持布尔的 ++(增量),但不支持 -- (减量)。这只是一个随机决定,还是有某些原因?

这样编译:

static HMODULE hMod = NULL;
static bool once = false;
if (!once++)
    hMod = LoadLibrary("xxx");

这不是:

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");

【问题讨论】:

hm,xcode 和 gcc 编译器相同 是的,++onceonce++ 使用 gcc,但不使用递减量。 也许重新标记“历史”而不是“运营商关键字”,所以这与所有其他有趣的解释组合在一起,如果你考虑历史,为什么各种疯狂的事情是合理的? :) 注意,从 C++17 开始,bool 的预增量运算符已被弃用,souce。 这可以替换为std::exchange(once,false)(注意:not atomic),如果你想要一些不被弃用的东西。 【参考方案1】:

它来自使用整数值作为布尔值的历史。

如果xint,但我按照if(x)... 将其用作布尔值,那么递增将意味着无论其在操作之前的真值如何,它的真值都是true在它之后(除非溢出)。

但是,如果只知道x 的真值,就不可能预测-- 的结果,因为它可能导致false(如果整数值为1)或true(如果整数值是任何其他值 - 特别是这包括 0 [false] 和 2 或更多 [true])。

所以作为简写的++ 有效,而-- 没有。

++ 允许在 bools 上与此兼容,但在标准中已弃用它,并在 C++17 中将其删除。


这假设我x 用作布尔值,这意味着在我经常使用++ 导致溢出之前不会发生溢出。即使使用 char 作为使用的类型,CHAR_BITS 像 5 一样低,这也是 32 次之后才不再起作用(这仍然足以证明这是一种不好的做法,我不是为这种做法辩护,只是解释为什么它有效)对于 32 位 int,我们当然必须使用 ++ 2^32 次才能成为问题。虽然使用--,但如果我从true 的值1 开始,或者从0 开始并且之前恰好使用过一次++,它只会导致false

如果我们从一个略低于 0 的值开始,情况就不同了。实际上,在这种情况下,我们可能希望 ++ 最终产生 false 值,例如:

int x = -5;
while(++x)
  doSomething(x);

但是,此示例将x 视为除条件之外的所有位置的int,因此它相当于:

int x = -5;
while(++x != 0)
  doSomething(x);

这与仅使用 x 作为布尔值不同。

【讨论】:

谢谢。很高兴知道我仍然可以给出这样的答案,因为我实际上已经写了一行 C++ :) 但如果 x 为 -1(在某些平台如 VB 中为 TRUE),则 ++x 将为 FALSE。 @James,在 C 和 C++ 中,当我说(“禁止溢出”)时,我想到的就是这种情况。实际上,在 VB 中,任何非零都具有真值 TRUE(就像在 C 中一样),但是它们具有 -1 而不是 1 作为真正的布尔运算的结果,因为 NOT(TRUE) 为 FALSE,NOT(FALSE) 为 TRUE,x OR TRUE 为 TRUE,x OR FALSE 为 x,x AND FALSE 为 FALSE,x AND TRUE 为 x 等,使用相同的运算符进行布尔运算和按位运算(因为 VB 假定二进制补码,因此 -1 全部为 1 位)。但是,如果编码器没有捕捉到 2 (true) AND 4 (true) 结果为 0 (false),这可能会导致 VB 中出现一些奇怪的错误。 @JonHanna:ANSI C89 是第一个 C 标准。 ANSI C 委员会发明了<limits.h> 标头和CHAR_BIT 宏。在此之前,我想理论上可能存在char 小于 8 位的实现,但据我所知没有。特别是,K&R1(1978 年出版)列出了 4 个示例实现,它们都有 8 位或 9 位 char @JonHanna:符合 C 的实现必须CHAR_BIT >= 8。该标准没有考虑到难以实现的目标。 (当然,你可能有一个不合格的实现。)【参考方案2】:

ANSI ISO IEC 14882 2003 (c++03):

5.2.6-2

后缀--的操作数是 类似于后缀递减 ++ 运算符,但操作数不得为 bool 类型。 [注:对于 前缀递增和递减,见 5.3.2. ]

不出所料...

5.3.2-2

前缀--的操作数被修改 通过减 1. 操作数应 不是布尔类型。要求 在前缀的操作数上 -- 和 其结果的性质否则 与前缀 ++ 相同。 [笔记: 对于后缀递增和递减, 见 5.2.6。 ]

另外,5.6.2-1 和 5.3.2-1 提到布尔值的 ++ 应该是正确的,附件 D-1 说布尔值的 ++ 已弃用。

【讨论】:

@BlueRaja:请参阅 Jon Hanna 的回答。【参考方案3】:

由于历史原因,这得到了支持。但请注意... 不推荐使用带有 ++ 运算符的 bool 类型的操作数,请参阅 C++ 标准 (n3092) 中的第 5.3.2 节

5.3.2 递增和递减[expr.pre.incr]

前缀++的操作数被修改 加 1,如果是则设置为 true bool(此用法已弃用)。这 操作数应为可修改的左值。 操作数的类型应为 算术类型或指向 a 的指针 完全定义的对象类型。这 result 是更新后的操作数;它是 一个左值,如果它是一个位域 操作数是一个位域。如果 x 是 不是 bool 类型的,表达式 ++x 相当于 x+=1 [ 注意:见 加法(5.7)的讨论和 赋值运算符(5.17) 有关转换的信息。 ——尾注 ] 前缀--的操作数被修改 通过减 1. 操作数应 不是布尔类型。要求 在前缀的操作数上 -- 和 其结果的性质是 其他与前缀相同 ++。

【讨论】:

【参考方案4】: 对于旧标准 (C++98),这不是错误。 随着新标准的增加,布尔值已被弃用。 (C++11) 在 C++17 之前,您可以对布尔值使用增量。

【讨论】:

以上是关于布尔运算符 ++ 和 --的主要内容,如果未能解决你的问题,请参考以下文章

&= 和 |= 运算符是不是用于布尔短路?

为啥在java中不允许没有括号的赋值和布尔运算符

java的布尔运算符和位运算符

在 C++ 中对布尔值使用位运算符

布尔运算符 && 和 ||

布尔表达式