OR演算子の基礎と実践ガイド:論理ORとビットORの違い、短絡評価、言語別挙動を徹底解説

OR演算子とは — 基本定義と用途

OR演算子(英: OR operator)は、コンピュータサイエンスやプログラミングにおける「論理和(論理的なまたは)」や「ビット単位の和」を実現するための演算子です。状況や言語により意味合いや記法が異なり、大きく分けて以下の2種類があります。

  • 論理OR(logical OR): 真理値(Boolean)を扱い、少なくとも一方が真なら真を返す。
  • ビット単位OR(bitwise OR): 整数の各ビットごとにOR演算を適用して新しい値を作る。

真理表(Truth table)と基本法則

論理ORの真理表は単純です(A, B をブール値とする):

  • A = FALSE, B = FALSE → A OR B = FALSE
  • A = FALSE, B = TRUE → A OR B = TRUE
  • A = TRUE, B = FALSE → A OR B = TRUE
  • A = TRUE, B = TRUE → A OR B = TRUE

ブール代数としての基本法則:

  • 結合則: (A OR B) OR C = A OR (B OR C)
  • 交換則: A OR B = B OR A
  • 冪等律: A OR A = A
  • 吸収律: A OR (A AND B) = A
  • 単位元: A OR FALSE = A
  • 支配元: A OR TRUE = TRUE

論理ORと短絡評価(ショートサーキット)

多くの言語では論理ORに「短絡評価(short-circuit evaluation)」が適用されます。左側の式が真であれば右側は評価されません。これにより、副作用のある関数呼び出しを避けたり、null チェックを組み合わせて安全にアクセスしたりできます。

例(C/Java/JavaScriptの ||):

if (a != null && a.value == 10) { ... }  // && は左が false なら右を評価しない
if (x > 0 || expensiveCheck()) { ... }    // x>0 が true なら expensiveCheck() は実行されない

ただし、言語によっては返す値がブールでない場合もあります(後述)。短絡評価の存在は副作用や最適化に関連する重要な挙動です。

言語ごとの記法と挙動(代表例)

以下、代表的言語ごとのORの記法と特徴をまとめます。

  • C / C++ / Java / JavaScript(C系): 論理OR は ||、ビットOR は |。論理OR は短絡評価する。論理演算子は結果を真(1)/偽(0)で返す(厳密には言語仕様に依存)。
  • Python: 論理OR はキーワード or。短絡評価するが、返り値はブールではなく「最初に真と評価されるオブジェクト」または最後のオブジェクト(truthy/falsey の評価結果)を返す。
  • JavaScript: 論理OR は ||。短絡評価し、返り値は boolean ではなく「左オペランドが truthy なら左、そうでなければ右」を返す(値の返し方は便利だが型に注意)。
  • SQL: OR は三値論理(TRUE / FALSE / UNKNOWN(NULL))を持つ。NULL が絡むと結果が UNKNOWN になる場合があるため、NULL の取り扱いに注意。
  • シェル(Unix 系): 論理和に近い表現は && や || をコマンドの成否で使う。パイプ(|)は別物(標準出力/入力の接続)。

ビット単位ORの用途と性質

ビット単位OR(|)は整数の各ビットごとに OR を行います。同じビット位置にどちらか1つでもビットが立っていれば、その位置は1になります。典型的な用途:

  • フラグやビットマスクの設定(例: 権限フラグを合成する)
  • ビット演算を使った高速な集合演算や状態の合成
  • 低レベルのハードウェア制御やプロトコルのビットフィールド操作

注意点:

  • 負の数は多くの言語で二の補数表現を使っているため、ビット演算での扱いに注意(符号拡張など)。
  • JavaScript のビット演算は内部で数値を32ビット符号付き整数に変換してから演算するため、大きな整数や浮動小数点の取り扱いで予期しない結果になることがある。

型の変換と副作用:弱い型付け言語の注意点

JavaScript や PHP のような弱い(動的)型付け言語では、論理ORやビットORの前に暗黙の型変換が行われます。特に JavaScript の論理OR(||)は「短絡評価+値を返す」ため、真偽値だけでなくオブジェクトや文字列、数値がそのまま返ることがあります(例: "" || "default" は "default")。これによりデフォルト値の割り当てに頻繁に使われますが、値の型と truthy/falsey の判断を理解しておかないとバグになります。

SQL における OR と NULL(三値論理)

SQL の OR は三値論理を持ち、どちらか一方が TRUE なら TRUE、両方 FALSE なら FALSE、どちらかが UNKNOWN(NULL)を含む場合は条件によって UNKNOWN になることがあります。例えば:

TRUE OR NULL  = TRUE
FALSE OR NULL = NULL (UNKNOWN)
NULL  OR NULL = NULL

このため、NULL を含む条件式では COALESCE や IS NULL を使った明示的な扱いが必要です。

演算子の優先順位と括弧の重要性

OR は多くの言語で優先順位が低く、AND(&&, and)よりも結合が弱いです。従って、複雑な条件式を書く際は括弧で明確にすることが推奨されます。ビット演算でも XOR(^)や AND(&)との優先順位に注意してください。読みやすさとバグ防止の両面から、適切に括弧を使いましょう。

実践的なテクニックと落とし穴

  • 短絡評価で安全に null チェックを行う:obj != null && obj.method() のように使う。
  • JS の || をデフォルト値に使うと 0 や "" が誤って置換される可能性がある(ES2020 の ??(Nullish coalescing)演算子が代替になる)。
  • ビットマスクの合成には OR、消去には AND と補数(~)を組み合わせる。
  • パフォーマンス面では、単純な OR/| はほとんどのケースで十分高速だが、ホットループの極限最適化では分岐削減(分岐予測)やSIMD命令の利用が検討される。

具体例(コードスニペット)

言語ごとの振る舞いを示す短い例:

// JavaScript: 短絡評価+値を返す
const a = 0 || "def"; // "def" が返る(0 は falsy)

// Python: or は最初の truthy を返す
x = "" or "default"  # "default"

// C: 論理OR は 0/1 を返す、短絡評価
if (a || b) { /* aやbのどちらかが真ならここ */ }

// Bitwise OR: ビット毎に OR
let mask = 0b0101 | 0b0011; // 結果 0b0111

まとめ

OR演算子は用途によって意味合い(論理OR と ビットOR)が変わり、言語ごとの記法や評価ルール(短絡評価、返り値の型、三値論理等)を理解することが重要です。典型的な用途は条件の結合やフラグの合成ですが、弱い型付け言語やNULLを扱う環境では注意深い設計とテストが求められます。

参考文献