TL; DR
Cは、別の言語から!
and ~
演算子を継承しました。両方&&
と||
は、数年後に別の人によって追加されました。
ロングアンサー
歴史的に、Cは、BCPLに基づいた初期言語Bから発展しました。BCPLは、アルゴルに基づいたCPLに基づいていました。
C ++、Java、C#のgreat祖父であるAlgolは、プログラマーに直感的に感じられるようにtrueとfalseを定義しました。固有の積分値と同じ」。しかし、これの一つの欠点は、論理とビット単位ではないが、同じ操作することができないことである:任意の現代のコンピュータで~0
-1よりもむしろ1に等しく、~1
等しい-2なく0を(さらにいくつかの60歳のメインフレーム上に~0
-を表します0またはINT_MIN
、~0 != 1
これまでに作成されたすべてのCPUで、C言語標準は長年それを要求してきましたが、ほとんどの娘言語は符号と大きさまたは補数をまったくサポートすることさえしません)
Algolは、異なるモードを使用し、ブールモードと積分モードで演算子を異なる方法で解釈することにより、この問題を回避しました。つまり、ビット演算は整数型で1つであり、論理演算はブール型で1つでした。
BCPLには個別のブール型がありましたnot
が、ビット単位および論理的ではない単一の演算子がありました。このCの先駆者がその仕事をした方法は次のとおりでした。
trueのRvalueは、完全に1で構成されるビットパターンです。falseの右辺値はゼロです。
ご了承ください true = ~ false
(右辺値という用語は、Cファミリ言語ではまったく異なるものを意味するように進化していることがわかります。今日では、Cの「オブジェクト表現」と呼びます。)
この定義により、論理的およびビット単位で同じ機械語命令を使用できなくなります。Cがそのルートを行っていた場合、世界中のヘッダーファイルが言うでしょう#define TRUE -1
。
しかし、Bプログラミング言語は型指定が弱く、ブール型や浮動小数点型さえありませんでした。すべてがint
後継のC と同等でした。これにより、プログラムが論理値としてtrueまたはfalse以外の値を使用したときに何が起こったのかを言語が定義するのは良い考えになりました。最初に「ゼロに等しくない」との真正な表現を定義しました。これは、CPUゼロフラグが設定されたミニコンピューターで効率的でした。
当時、代替手段がありました:同じCPUにも負のフラグがあり、BCPLの真理値は-1であったため、代わりにBはすべての負の数値を真理として、すべての非負の数値を偽として定義した可能性があります。(このアプローチの残りの1つがあります。UNIXの多くのシステムコールは、同じ人によって同時に開発され、すべてのエラーコードを負の整数として定義します。そのシステムコールの多くは、失敗時に異なる負の値の1つを返します。)ありがたいことに、もっとひどかったかもしれません!
しかし、定義TRUE
として1
及びFALSE
として0
Bにはアイデンティティがあることを意味しないtrue = ~ false
、もはや開催され、そしてそれはビット単位と論理式の間で明確にするためにアルゴルを許さ強い型付けを落としていました。これには新しい論理否定演算子が必要でしたが、設計者はを選択しました。これは!
、おそらく不等号がすでに!=
であったためです。これは、等号の縦棒のようなものです。彼らは、どちらもまだ存在していないため、&&
または||
どちらも存在しないため、同じ慣習に従っていませんでした。
おそらく、&
B の演算子は設計どおりに壊れています。BおよびCにおいて、1 & 2 == FALSE
たとえ1
と2
の両方truthy値であり、Cは、一部追加することによって修正しようとした1つのミスであったB.で論理演算表現する全く直感的な方法がない&&
と||
、時間の主な関心事は、であったが最後に短絡を機能させ、プログラムをより速く実行します。これの証拠は、オペランドが両方とも真実であるにもかかわらず、^^
:1 ^ 2
が真実の値ではないことですが、短絡の恩恵を受けることはできません。