web-dev-qa-db-ja.com

C ++のブール型が++をサポートするのに-をサポートしないのはなぜですか?

演算子--は存在するのに、演算子++は存在しないのはなぜですか?

C++で試しましたが、私の質問が他の言語に当てはまるかどうかわかりません。私も知ってうれしいです。

知っています 、ブール値で演算子++を使用できます。これは、ブール値をtrueに等しくします。

bool b = false;
b++;
// Now b == true.

演算子--を逆に使用できないのはなぜですか?

bool b = true;
b--;
// Now b == false;

あまり役に立ちませんが、気になります。

Cの昔は、ブール型はありませんでした。人々はintをブールデータの格納に使用しましたが、ほとんどが機能しました。 ゼロは偽でした そして、他のすべては真でした。

これは、あなたがint flag = 0;以降はflag++値はtrueになります。これは、フラグの値が何であっても機能します (あなたがたくさんそれをしたのでなければ、それはロールオーバーしてゼロに戻ったが、それを無視することができます) -値が1のときにフラグをインクリメントすると、2が返されますが、これはまだ真でした。

一部の人々はこれを無条件にブール値をtrueに設定するために使用しました。 イディオマティック になったかどうかはわかりませんが、コードによっては異なります。

これは--、値が1(それである可能性があります)以外の場合でも、値はfalseではありません。そして、それがすでに偽であった場合(0)そして、あなたはそれにデクリメント演算子を実行しました、それはfalseのままではありません。

初期の段階でCからC++にコードを移動する場合、C++に含まれるCコードが引き続き機能することが非常に重要でした。そして C++の仕様 (セクション5.2.6(71ページ))では次のようになります。

後置++を適用して得られる値は、演算子を適用する前のオペランドの値です。 [注:取得した値は元の値のコピーです]オペランドは変更可能な左辺値でなければなりません。オペランドの型は、算術型または完全なオブジェクト型へのポインターです。結果が記録された後、オブジェクトのタイプはboolである場合を除いて、オブジェクトに1を追加することでオブジェクトの値が変更されます。この場合、オブジェクトはtrueに設定されます。 [注:この使用は非推奨です。付録Dを参照してください。]

Postfixのオペランド-オペランドのタイプがboolであってはならないことを除いて、postfix ++演算子と同様にデクリメントされます。

これは、セクション5.3.2で再び言及されています(前置演算子の場合-5.2.6はpostfixにありました)。

ご覧のとおり、これは非推奨であり(ドキュメントの付録D、709ページ)、使用しないでください。

しかし、それが理由です。そして、時にはあなたはコードを見るかもしれません。しかし、それをしないでください。

54
user40980

ブール型としてintまたは類似のものを使用したレガシーコードに部分的に対処するため。

2
Mike Graham

この質問の歴史的重要性を理解するには、Therac-25のケースを考慮する必要があります。 Therac-25は、がん患者に放射線を照射する医療機器でした。安全性の低い実績に起因する不適切なプログラミング慣行に悩まされていました(複数の死が原因)。

http://courses.cs.vt.edu/professionalism/Therac_25/Therac_1.html

(3ページの一番下に移動します)

セットアップテストルーチンを通過するたびに、上部コリメータ位置チェック(Class3と呼ばれる共有変数)が増加します。 Class3がゼロ以外の場合、不整合があり、処理を続行できません。 Class3のゼロ値は、関連するパラメーターが治療と一致しており、ビームが抑制されていないことを示します。

...

マシンのセットアップ中、セットアップテストは他のイベントが発生するのを待って再スケジュールするため、数百回実行されます。コードでは、Class3変数は、セットアップテストの各パスで1ずつ増加します。 Class3変数は1バイトであるため、最大値は10進数255のみです。したがって、セットアップテストコードを256回通過するたびに、変数がオーバーフローし、値がゼロになります。つまり、セットアップテストを256回パスするたびに、上部コリメータはチェックされず、上部コリメータの障害は検出されません。露出オーバーは、Class3がゼロにロールオーバーした正確な瞬間にオペレーターが「設定」ボタンを押したときに発生しました。したがって、Chkcolは実行されず、F $ malは上部コリメータがまだフィールドライトの位置にあることを示すように設定されていませんでした。ソフトウェアは、ターゲットを設置せず、スキャンも行わずに、25 MeV全体をオンにしました。非常に集中した電子ビームが生じ、それは経路にあるステンレス鋼の鏡によって散乱され、偏向された。

Therac-25はboolで_operator++_と同等のものを使用しました。ただし、使用したプログラミング言語はC++ではなく、データ型はboolではありませんでした。ただし、C++の保証とは異なり、通常の整数型は増加し続けます。それらのデータ型は_uint8_t_と同等でした。

C++は、このようなプログラミングに慣れている人々のために_operator++_を維持することを決定しましたが、値をインクリメントするのではなく、単にtrueに設定して、このようなことを防ぎます。

operator++(bool)は非推奨であることに注意してください。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

C++ 14の付録D:

D.1 boolオペランドを持つインクリメント演算子
++演算子でbool型のオペランドを使用することは非推奨です(5.3.2および5.2.6を参照)。

1
David Stone