
C言語基礎|論理演算子とビット演算子の違い
見た目が似てても中身は別モノ!&& と & を取り違えると、答えも動きもガラッと変わる。
論理演算子とビット演算子、ここでスッキリ分けよう
C言語には「似ている記号」がいくつかあります。中でも混同しやすいのが、
- 論理演算子(&&、||、!)
- ビット単位の論理演算子(&、|、~、^)
この2グループです。
パッと見は似てますが、扱う対象が違うので、結果も考え方も別になります。
- 論理演算子:値を「真(0以外)/偽(0)」として判定し、結果は基本的に 0 または 1
- ビット演算子:整数の各ビットを 0/1 とみなして演算し、結果はビット列そのもの
この記事では、表と図で「何が違うのか」を整理しながら、よくある事故(意図せず & を使った、短絡評価を期待していた等)も一緒に押さえます。

まず結論:何が違うの?
論理演算子とビット演算子の根本的な違い
| 観点 | 論理演算子 | ビット演算子 |
|---|---|---|
| 対象 | 真偽(0かそれ以外) | ビット列(各ビット) |
| 主な演算子 | &&、 | |
| 判定基準 | 0 が偽、0以外が真 | 0 が偽、1 が真(各ビットごと) |
| 結果 | 0 または 1 になりやすい | ビット列の結果(0や1に限らない) |
| よく使う場面 | if の条件、ループ条件 | マスク処理、フラグ操作、ビット抽出 |
| 重要な特徴 | && と |
表の説明
この表は「同じAND/ORっぽい見た目でも、そもそも見ている世界が違う」という整理です。
論理演算子は “真偽の世界”、ビット演算子は “ビット列の世界” だと思うと混乱しにくいです。
それぞれの「書式」と「何をする命令か」
論理演算子(真偽を扱う)
| 演算子 | 書式 | 何をする命令? | 結果のイメージ |
|---|---|---|---|
| && | a && b | a と b が両方真なら真 | 真なら 1、偽なら 0 |
| || | a || b | a と b のどちらかが真なら真 | 真なら 1、偽なら 0 |
| ! | !a | a が偽なら真、真なら偽 | 反転(0/1になりやすい) |
ビット演算子(各ビットを扱う)
| 演算子 | 書式 | 何をする命令? | 結果のイメージ |
|---|---|---|---|
| & | a & b | 各ビットでAND | ビット列が残る |
| | | a | b | 各ビットでOR | ビット列が立つ |
| ^ | a ^ b | 各ビットでXOR | ビット列が反転する場所が出る |
| ~ | ~a | 全ビット反転 | ビット列が反転した値 |
表の説明
- && と & は「AND」という名前が同じでも、前者は真偽判定、後者はビット判定です。
- || と | も同様です。
- ! と ~ も “否定っぽい”けど、! は真偽の否定、~ は全ビット反転です。
具体例:5 & 4 と 5 && 4 はこう違う
提示文の要点を、図として見える形にします。
図:ビット演算 5 & 4(ビット列としてAND)
5 = 0101
4 = 0100
& = 0100 → 4
図:論理演算 5 && 4(真偽としてAND)
5 は 0 ではない → 真
4 は 0 ではない → 真
真 && 真 → 真 → 1
図の説明
- 5 & 4 は「0101 と 0100 の各ビットでAND」だから 0100 になって 4。
- 5 && 4 は「どちらも非0だから真」なので 1。
同じ “ANDっぽい” でも、結果が 4 と 1 に分かれるのが決定的な違いです。
事故が多いポイント:短絡評価の有無
論理演算子 && と || は、条件が決まった時点で 右側を評価しないことがあります(短絡評価)。
ビット演算子 & と | は、基本的に 両側を評価します。
短絡評価の違い
| 書式 | 評価のしかた | ありがちな用途 |
|---|---|---|
| a && b | a が偽なら b を評価しない | ポインタがNULLでない時だけ次を確認 |
| a || b | a が真なら b を評価しない | 先に真が分かったら確定 |
| a & b | 両方評価してからビットAND | マスク処理 |
| a | b | 両方評価してからビットOR | フラグの合成 |
表の説明
「安全確認のために右側を評価したくない」なら && や || が向いています。
ビット演算は “評価制御” が目的ではなく、ビット列の加工が目的です。
よく使う場面の違い(実務イメージ)
どう使い分ける?
| やりたいこと | 使うのはどっち? | 例 |
|---|---|---|
| 条件分岐したい | 論理演算子 | if (x > 0 && x < 10) |
| 0かどうか調べたい | 論理演算子 | if (n != 0) / if (!n) |
| フラグを立てたい(ビットON) | ビット演算子 | flags |= mask |
| フラグを消したい(ビットOFF) | ビット演算子 | flags &= ~mask |
| 特定ビットだけ取り出したい | ビット演算子 | x & 0x0F |
表の説明
- 条件式は “真偽” の世界なので論理演算子。
- フラグやマスクは “ビット列” の世界なのでビット演算子。
この切り替えができると、混同が一気に減ります。
サンプルプログラム
論理演算子とビット演算子の違いを確認するプログラムです。
プロジェクト名:chap7-20-1 ソースファイル名:chap7-20-1.c
// 論理演算子とビット演算子の違いを確認する
#include <stdio.h>
int main(void)
{
int a = 6; // 0110
int b = 3; // 0011
printf("論理演算とビット演算の違いを確認します。\n");
printf("a = %d, b = %d\n\n", a, b);
printf("a & b = %d (ビットAND:各ビットでAND)\n", a & b);
printf("a && b = %d (論理AND:非0なら真として判定)\n\n", a && b);
printf("a | b = %d (ビットOR:各ビットでOR)\n", a | b);
printf("a || b = %d (論理OR:どちらか非0なら真)\n\n", a || b);
printf("!a = %d (論理否定:aが0なら1、非0なら0)\n", !a);
printf("~a = %d (ビット反転:全ビットを反転)\n", ~a);
return 0;
}このプログラムで何が分かる?
- a & b は 6(0110) と 3(0011) の共通する 1 のビットだけが残るので 2(0010) になります。
- a && b は 6 も 3 も非0なので真 && 真 → 1 になります。
- !a は真偽の反転、~a はビット列の反転なので、そもそも結果の意味が違います。
図で理解:6 と 3 の AND を2種類で比較
図:6 & 3(ビットとして計算)
6 = 0110
3 = 0011
& = 0010 → 2
図:6 && 3(真偽として計算)
6 は非0 → 真
3 は非0 → 真
真 && 真 → 1
図の説明
ここでも “2” と “1” に分かれます。
ビット演算は「ビット列の加工結果」、論理演算は「条件の成立(真偽)」が答えです。
つまずきやすいミニ注意
- 条件式で & や | を使うと、意図せず両側が評価されてしまうことがあります。
- フラグ判定で && を使うと、ビットの判定ではなく “非0かどうか” の判定になります。
- ! と ~ はまったく別用途です(! は真偽、~ はビット反転)
