布尔运算符++和 –

今天,在编写一些Visual C ++代码时,我遇到了一些让我感到惊讶的东西。 看来C ++支持bool的++(增量),而不是 – (递减)。 这只是一个随机的决定,还是有这个背后的原因呢?

这编译:

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"); 

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

如果x是一个int ,但是我将它作为if(x)...的布尔值来使用,那么递增将意味着无论它在操作之前的真值如何,在它之后它将具有真值(禁止溢出)。

然而,仅仅预测x的真值的结果是不可能的,因为它可能导致false (如果积分值为1)或true (如果积分值是其他值 – 特别是包括0 [ false ]和2或更多[ true ])。

所以,作为一个简短的++工作,并没有。

在bools上允许++与此兼容,但是在标准中不再使用它。


这假设我使用x作为布尔值,这意味着溢出不会发生,直到我做了++往往足以导致它自己的溢出。 即使使用chartypes和CHAR_BITS类似5的东西,这是32倍之前,这不再工作(这仍然是足够的论据,这是一个不好的做法,我不是捍卫的做法,只是解释为什么它的作品)对于一个32位的int我们当然必须使用++ 2 ^ 32次之前,这是一个问题。 使用--虽然只会导致false如果我开始使用值为1为true ,或从0开始,使用++之前精确一次。

如果我们从低于0的数值开始,这是不同的。事实上,在这种情况下,我们可能希望++最终导致false值,例如:

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

但是,这个例子将x视为除了条件之外的int ,所以它相当于:

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

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

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

5.2.6-2

后缀的操作数 – 类似于后缀++操作符递减,除了操作数的types不是booltypes。 [注:前缀增加和减less,见5.3.2。 ]

不出所料

5.3.2-2

前缀的操作数 – 通过减1来修改。操作数的types不能是booltypes。 对前缀操作数的要求 – 及其结果的属性与前缀++的相同。 [注:后缀增量和减量,见5.2.6。 ]

5.6.2-1和5.3.2-1也提到++对于bools应该是真的,附录D-1说在++上bools已经被弃用了。

由于历史原因,这是支持。 但是请注意…不build议使用带有++运算符的bool型操作数,请参见C ++标准(n3092)中的第5.3.2节。

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

  • 前缀++的操作数是通过加1来修改的,如果是bool(这个用法已被废弃),则设置为true。 操作数应该是一个可修改的左值。 操作数的types应为算术types或指向完全定义的对象types的指针。 结果是更新的操作数; 它是一个左值,如果操作数是位域,则它是一个位域。 如果x不是booltypes,则expression式++ x等价于x + = 1 [注意:有关转换的信息,请参见加法(5.7)和赋值运算符(5.17)的讨论。 – 注意]
  • 前缀的操作数 – 通过减1来修改。操作数的types不能是booltypes。 对前缀操作数的要求 – 及其结果的属性与前缀++的相同。
  • 用旧的标准(C ++ 98),这不是一个错误。
  • 随着新标准的增加,一个布尔值被弃用。 (C ++ 11)
  • 你可以在布尔值上使用增量,直到C ++ 17。