布尔运算符 ++ 和 --
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 编译器相同 是的,++once
和 once++
使用 gcc,但不使用递减量。
也许重新标记“历史”而不是“运营商关键字”,所以这与所有其他有趣的解释组合在一起,如果你考虑历史,为什么各种疯狂的事情是合理的? :)
注意,从 C++17 开始,bool
的预增量运算符已被弃用,souce。
这可以替换为std::exchange(once,false)
(注意:not atomic),如果你想要一些不被弃用的东西。
【参考方案1】:
它来自使用整数值作为布尔值的历史。
如果x
是int
,但我按照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 之前,您可以对布尔值使用增量。【讨论】:
以上是关于布尔运算符 ++ 和 --的主要内容,如果未能解决你的问题,请参考以下文章