布尔运算符++和-


104

今天,在编写一些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");

2
hm,与xcode和gcc编译器相同
Vladimir 2010年

是的,++onceonce++gcc一起工作,但不减少。
贾斯汀·阿迪尼

也许重新标记“历史”而不是“操作员-关键字”,所以这与所有其他有趣的解释归为一类,以至于如果考虑历史,为什么各种疯狂的事情是合理的?:)
乔恩·汉娜

请注意,从C ++ 17开始,bool不赞成使用pre-incre运算符souce
cogle

如果您希望不使用某些东西,可以将其替换为std::exchange(once,false)(注意:不是原子的)。
golvok

Answers:


90

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

如果xint,但我将其用作布尔值,if(x)...则递增将意味着无论操作前其真值如何,其后的真值都将为真true(禁止溢出)。

但是,--仅根据的真值预测给定知识的结果是不可能的x,因为它可能会导致false(如果积分值为1)或true(如果积分值为其他任何值-特别是包括0 [ false]和2或更多[ true])。

因此,作为速记方式++--没有。

++ 为了与布尔型兼容,允许在布尔型上使用,但在标准中已弃用。


假设我将其x用作布尔值,这意味着只有在我做得++足够多而导致自身溢出之前,才可能发生溢出。即使将char作为使用的类型并将其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作布尔值不同。


1
谢谢。很高兴知道,鉴于我实际上已经编写了C ++代码以来,我仍然可以给出类似的答案:)
Jon Hanna 2010年

8
但是,如果x为-1(在VB等平台上为TRUE),则++ x为FALSE。
詹姆斯·柯伦

4
@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(真)和4(真)的结果为0(假),则这可能会在VB中引起一些奇怪的错误。
乔恩·汉纳

2
@JonHanna:ANSI C89是第一个C标准。ANSI C委员会发明了<limits.h>标题和CHAR_BIT宏。在此之前,我认为理论上可能有char比8位窄的实现,但据我所知没有。特别是,K&R1(于1978年发布)列出了4个示例实现,所有示例实现均具有8位或9位char
基思·汤普森

1
@JonHanna:合格的C实现必须具有CHAR_BIT >= 8。该标准没有为困难的目标留出余地。(当然,您可能会有一个不合格的实现。)
Keith Thompson

29

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

5.2.6-2

postfix的操作数-与postfix ++运算符类似地递减,不同之处在于该操作数的类型不得为bool。[注意:有关前缀递增和递减的信息,请参阅5.3.2。]

毫不奇怪...

5.3.2-2

前缀-的操作数通过减去1进行修改。操作数的类型不得为bool。前缀操作数的要求-以及其结果的属性与前缀++相同。[注意:有关后缀的增减,请参阅5.2.6。]

另外5.6.2-1和5.3.2-1提到布尔值++应该是正确的,而附件D-1则表示不赞成使用布尔值++。


3
@BlueRaja:请参阅乔恩·汉纳的答案。
贾斯汀·阿迪尼

9

由于历史原因,对此表示支持。但请注意, 不赞成在++运算符中使用bool类型的操作数,请参见C ++ Standard(n3092)中的5.3.2节

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

  • 前缀++的操作数通过加1进行修改,如果为bool,则将其设置为true(不建议使用此用法)。操作数应为可修改的左值。操作数的类型应为算术类型或指向完全定义的对象类型的指针。结果是更新的操作数;它是一个左值,如果操作数是一个位字段,它是一个位字段。如果x的类型不是bool,则表达式++ x等效于x + = 1 [注意:有关转换的信息,请参见加法(5.7)和赋值运算符(5.17)的讨论。—尾注]
  • 前缀-的操作数通过减去1进行修改。操作数的类型不得为bool。前缀操作数的要求-以及其结果的属性与前缀++相同。

3
  • 使用旧标准(C ++ 98),这不是错误。
  • 随着新标准的增加,不赞成使用布尔值。(C ++ 11)
  • 您可以在布尔值上使用递增,直到C ++ 17。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.