bool演算子++および-


104

今日、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");

2
hm、xcodeおよびgccコンパイラも同じ
Vladimir

うん、++onceonce++GCCとの仕事ではなく、デクリメントします。
Justin Ardini、2010

「operator-keyword」の代わりに「history」のタグを付け直すかもしれないので、これは、歴史を考えると、さまざまなクレイジーなことが合理的である理由について、他のすべての楽しい説明とグループ化されていますか?:)
ジョンハンナ

C ++ 17以降では、のインクリメント演算子boolは廃止予定であるsouceに注意してください。
cogle

非推奨ではないものを使用したい場合は、これをstd::exchange(once,false)(注:アトミックではない)に置き換えることができます。
golvok

回答:


90

これは、ブール値として整数値を使用した歴史から来ています。

場合xですintが、私はあたりとしてboolean型としてそれを使用していますif(x)...インクリメントその後は、操作の前に何でもその真理値、それは真実の価値がありますことを意味しますtrue(オーバーフローがなければ)、それの後に。

しかし、それは結果を予測することは不可能だ--だけの真理値の与えられた知識をx、それはにつながる可能性として、false(積分値が1の場合)またはtrue(積分値が他の何かがある場合-特にこれが含ま0 [ false]と2か詳細[ true])。

つまり、略記が++機能するようになり、機能--しませんでした。

++ これとの互換性のためにブールでは許可されていますが、その使用は標準では非推奨です。


これは、ブール値としてのみ使用することを前提としてますx。つまり、オーバーフローが発生する++ほど頻繁にオーバーフローが発生するまで、オーバーフローは発生しません。使用するタイプとしてcharを使用し、CHAR_BITS5のように低い値でも、これが機能しなくなる前に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

8
ただし、xが-1(VBなどの一部のプラットフォームではTRUE)の場合、++ xはFALSEになります。
James Curran

4
@ James、CとC ++では、私が言ったときに考えていたケースです( "オーバーフローを禁止する")。実際にVBでは、ゼロ以外のすべての真理値はTRUE(Cのように)ですが、真のブール演算の結果として、NOT(TRUE)がFALSE、NOT(FALSE)がTRUE、x ORであるため、真ではありません。 TRUEはTRUE、x OR FALSEはx、x AND FALSEはFALSE、x AND TRUEはxなどです(ブール演算とビット単位の演算には同じ演算子を使用します(VBは2の補数を想定しているため、-1はすべて1ビットです)。ただし、コーダーが2(true)AND 4(true)の結果が0(false)になることをキャッチしない場合、VBでいくつかの奇妙なバグが発生する可能性があります。
Jon Hanna

2
@JonHanna:ANSI C89は最初のC標準でした。ANSI C委員会が<limits.h>ヘッダーとCHAR_BITマクロを発明しました。それ以前は、理論的にはchar8ビットよりも狭い実装があったと思いますが、私の知る限りではありませんでした。特に、K&R1(1978年に公開)には、4つのサンプル実装がリストされています。これらの実装はすべて、8ビットまたは9ビットcharです。
キース・トンプソン、

1
@JonHanna:適合するCの実装に必要CHAR_BIT >= 8です。標準では、それが難しいターゲットを考慮に入れていません。(もちろん、非準拠の実装も可能です。)
キース・トンプソン

29

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

5.2.6-2

postfix-のオペランドは、オペランドがbool型であってはならないことを除いて、postfix ++演算子と同様にデクリメントされます。[注:プレフィックスの増分と減分については、5.3.2を参照してください。]

そして当然のことながら...

5.3.2-2

接頭辞のオペランド-1を減算して変更します。オペランドはbool型であってはなりません。接頭辞のオペランドの要件とその結果のプロパティは、それ以外は接頭辞++の要件と同じです。[注:後置インクリメントおよびデクリメントについては、5.2.6を参照してください。]

また、5.6.2-1および5.3.2-1は、ブール値の++はtrueである必要があると述べており、Annex D-1はブール値の++は非推奨であると述べています。


3
@BlueRaja:Jon Hannaの答えを見てください。
Justin Ardini、2010

9

歴史的な理由により、これはサポートされました。ただし、... ++演算子でのbool型のオペランドの使用は非推奨です。C++標準のセクション5.3.2を参照してください(n3092)

5.3.2インクリメントとデクリメント[expr.pre.incr]

  • 接頭辞++のオペランドは、1を追加することによって変更されるか、ブール値の場合はtrueに設定されます(この使用は非推奨です)。オペランドは変更可能な左辺値でなければなりません。オペランドの型は、算術型または完全に定義されたオブジェクト型へのポインターです。結果は更新されたオペランドです。これは左辺値であり、オペランドがビットフィールドの場合はビットフィールドです。xがbool型でない場合、式++ xはx + = 1と同等です[注:変換については、加算(5.7)と代入演算子(5.17)の説明を参照してください。—エンドノート]
  • 接頭辞のオペランド-1を減算して変更します。オペランドはbool型であってはなりません。接頭辞のオペランドの要件とその結果のプロパティは、それ以外は接頭辞++の要件と同じです。

3
  • 古い標準(C ++ 98)ではエラーではありません。
  • 新しい標準では、ブール値をインクリメントすることは非推奨です。(C ++ 11)
  • C ++ 17までは、ブール値の増分を使用できます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.