C言語の基本|比較と論理演算子

==や&&を日本語に読み替えれば、条件式の意味が見えてくる。比較と論理演算子を使って、プログラムに判断する力を持たせよう。

C言語では、計算結果を求めるだけでなく、値を比較して処理を選ぶこともできます。

たとえば、次のような判断です。

  • 点数が60点以上か
  • 入力された値が0ではないか
  • 在庫数が基準より少ないか
  • 年齢が20歳以上で、さらに会員でもあるか
  • 2つの条件のうち、どちらか一方を満たしているか

このような条件を作るときに使うのが、等価演算子、関係演算子、論理演算子です。

score >= 60

この式は、scoreが60以上かを調べます。

number != 0

この式は、numberが0ではないかを調べます。

(age >= 20) && is_member

この式は、年齢が20歳以上であり、なおかつ会員であるかを調べます。

比較や論理演算の結果は、条件が成り立つ場合は1、成り立たない場合は0になります。結果の型はint型です。

また、ifやwhileの条件判定では、0が偽、0以外が真として扱われます。この仕組みを理解すると、条件式を正しく読み取れるようになります。

比較や条件に使う3種類の演算子

比較や条件の組み立てに使う演算子は、次の3つのグループに分けて考えると分かりやすくなります。

分類主な役割演算子
等価演算子値が等しいか、異なるかを調べる==、!=
関係演算子値の大小関係を調べる>、>=、<、<=
論理演算子条件を組み合わせたり反転したりする&&、||、!

どの演算子も、条件を表す式を作るために使用します。

たとえば、scoreが75の場合を考えてみましょう。

score >= 60

75は60以上なので、式の結果は1です。

75 >= 60
結果:1
判定:真

次の式は成り立ちません。

score < 60
75 < 60
結果:0
判定:偽

図1:比較と論理演算子の3つのグループ

この図から分かること

等価演算子は2つの値が同じかどうか、関係演算子は2つの値の大小関係を調べます。

論理演算子は、比較によって作られた複数の条件を組み合わせたり、条件の真偽を反転したりするときに使います。

比較や論理演算の結果は、真なら1、偽なら0です。

等価演算子==と!=

等価演算子は、2つの値が同じか、異なっているかを判定します。

演算子意味式の例日本語での読み方
==等しいa == baとbは等しいか
!=等しくないa != baとbは異なるか

aとbがどちらも10の場合を考えてみましょう。

a == b

2つの値が等しいため、結果は1です。

10 == 10
結果:1

次の式では、2つの値が異なるかを調べます。

a != b

aとbは同じ値なので、結果は0です。

10 != 10
結果:0

aが10、bが15なら、結果は反対になります。

判定結果
10 == 15等しくない0
10 != 15異なっている1

==は等しいかを調べる

==は、左辺と右辺の値が等しいかを比較します。

number == 100

numberが100なら、式の結果は1です。numberが100以外なら、結果は0です。

ifの条件では、次のように使用できます。

if (number == 100) {
    printf("numberは100です。\n");
}

numberが100の場合だけ、波括弧内のprintfが実行されます。

!=は異なるかを調べる

!=は、左辺と右辺の値が異なるかを比較します。

number != 0

numberが0以外なら、式の結果は1です。numberが0なら、結果は0です。

if (number != 0) {
    printf("numberは0ではありません。\n");
}

!=は、0ではないことを確認してから計算したい場合などによく使われます。

==と=を間違えないようにする

C言語では、==と=の役割が異なります。

演算子役割
==2つの値が等しいか比較するnumber == 123
=右辺の値を左辺へ代入するnumber = 123

次の条件式は、numberと123を比較しています。

if (number == 123) {
    printf("numberは123です。\n");
}

一方、次の書き方は比較ではありません。

if (number = 123) {
    printf("この処理が実行されます。\n");
}

number = 123によって、numberへ123が代入されます。さらに、代入式全体の値も123になります。

C言語では0以外が真として扱われるため、123は真です。その結果、ifの中の処理が実行されます。

numberへ123を代入
        ↓
代入式の値は123
        ↓
123は0以外なので真
        ↓
ifの処理を実行

この間違いは、必ずしもコンパイルエラーになるとは限りません。コンパイラによっては警告が表示されますが、プログラムとして実行できる場合があります。

条件式で値が等しいか調べたいときは、==を使いましょう。

関係演算子で大小を比較する

関係演算子は、2つの値の大小関係を判定します。

演算子意味式の例日本語での読み方
>より大きいa > baはbより大きいか
>=以上a >= baはb以上か
<より小さいa < baはbより小さいか
<=以下a <= baはb以下か

aが12、bが8の場合を考えてみましょう。

判定内容結果
a > b12は8より大きい1
a >= b12は8以上1
a < b12は8より小さい0
a <= b12は8以下0

>と>=の違い

は、左辺が右辺より大きい場合に真になります。2つの値が同じ場合は偽です。

score > 60

scoreが60の場合、60は60より大きくないため、結果は0です。

=は、左辺が右辺以上の場合に真になります。同じ値も条件に含まれます。

score >= 60

scoreが60の場合、60は60以上なので結果は1です。

scoreの値score > 60score >= 60
5900
6001
6111

条件に境界の値を含めるかどうかを確認して使い分けましょう。

<と<=の違い

<は、左辺が右辺より小さい場合に真になります。同じ値は含みません。

temperature < 30

temperatureが30の場合、結果は0です。

<=は、左辺が右辺以下の場合に真になります。同じ値も含みます。

temperature <= 30

temperatureが30の場合、結果は1です。

temperatureの値temperature < 30temperature <= 30
2911
3001
3100

関係演算子の書き方に注意する

以上と以下を表す演算子は、>=と<=です。

次の演算子はC言語にはありません。

=>
=<

また、2つの記号の間に空白を入れてはいけません。

> =
< =

=と<=は、それぞれ2文字で1つの演算子です。

score >= 60
score <= 100
2つの在庫数を比較して結果を表示するプログラム

ファイル名:6_7_1.c

#include <stdio.h>

int main(void)
{
    int current_stock;
    int standard_stock;

    printf("2つの在庫数を入力してください。\n");

    printf("現在の在庫数 > ");
    scanf("%d", ¤t_stock);

    printf("基準の在庫数 > ");
    scanf("%d", &standard_stock);

    printf("\n[等価演算子の結果]\n");
    printf("%d == %d : %d\n",
           current_stock, standard_stock,
           current_stock == standard_stock);

    printf("%d != %d : %d\n",
           current_stock, standard_stock,
           current_stock != standard_stock);

    printf("\n[関係演算子の結果]\n");
    printf("%d >  %d : %d\n",
           current_stock, standard_stock,
           current_stock > standard_stock);

    printf("%d >= %d : %d\n",
           current_stock, standard_stock,
           current_stock >= standard_stock);

    printf("%d <  %d : %d\n",
           current_stock, standard_stock,
           current_stock < standard_stock);

    printf("%d <= %d : %d\n",
           current_stock, standard_stock,
           current_stock <= standard_stock);

    printf("\n1は真、0は偽を表します。\n");

    return 0;
}
実行結果の例

現在の在庫数に48、基準の在庫数に60を入力した場合です。

2つの在庫数を入力してください。
現在の在庫数 > 48
基準の在庫数 > 60

[等価演算子の結果]
48 == 60 : 0
48 != 60 : 1

[関係演算子の結果]
48 >  60 : 0
48 >= 60 : 0
48 <  60 : 1
48 <= 60 : 1

1は真、0は偽を表します。

比較結果を表示するプログラムの解説

current_stockには48、standard_stockには60が格納されています。

最初に、2つの値が等しいかを調べています。

current_stock == standard_stock

48と60は等しくないため、結果は0です。

次に、2つの値が異なるかを調べています。

current_stock != standard_stock

48と60は異なるため、結果は1です。

大小関係の比較では、48が60より小さいかを調べる式が真になります。

current_stock < standard_stock
current_stock <= standard_stock

そのため、この2つの結果は1です。

比較式は、計算結果として1または0を作ります。このプログラムでは、その結果をprintfの%dで直接表示しています。

論理演算子で条件を組み合わせる

論理演算子は、複数の条件を組み合わせたり、条件の真偽を反転したりするときに使います。

演算子意味式の例日本語での読み方
&&論理積、かつ(a > 0) && (b > 0)aもbも正である
||論理和、または(a > 0) || (b > 0)aまたはbが正である
!論理否定、ではない!is_ready準備完了ではない

&&と||は、2つの条件を組み合わせます。!は、1つの条件の真偽を反転します。

&&は両方が真の場合だけ真になる

&&は、左右の条件が両方とも真の場合にだけ、結果が1になります。

(age >= 20) && is_member

この式は、年齢が20歳以上であり、さらに会員でもあるという意味です。

左の条件右の条件&&の結果
000
010
100
111

どちらか一方でも偽なら、式全体は偽です。

たとえば、ageが25、is_memberが1の場合を考えてみましょう。

age >= 20は真
is_memberも真
両方が真なので、&&の結果は1

is_memberが0の場合は、年齢条件を満たしていても、式全体の結果は0です。

||はどちらかが真なら真になる

||は、左右の条件のうち、少なくとも一方が真なら結果が1になります。

has_ticket || has_pass

この式は、チケットを持っている、または通行証を持っているという意味です。

左の条件右の条件||の結果
000
011
101
111

両方とも偽の場合だけ、式全体が偽になります。

!は真と偽を反転する

!は、条件の真偽を反転する演算子です。

!is_member

is_memberが真なら、!is_memberは偽になります。

is_memberが偽なら、!is_memberは真になります。

元の値!を付けた結果
01
10
50
-20

C言語では0以外が真なので、5や-2も真です。!を付けると偽を表す0になります。

次の2つの条件は、同じ意味になります。

!(a == b)
a != b

どちらも、aとbが等しくない場合に真になります。

図2:&&・||・!による真偽の変化

この図から分かること

&&は、組み合わせた条件が両方とも真の場合だけ、結果が真になります。

||は、どちらか一方でも真なら、結果が真になります。両方とも偽の場合だけ、結果が偽です。

!は、真を偽に、偽を真に反転します。

C言語では0が偽、0以外が真

ifやwhileなどの条件では、整数値が次のように判断されます。

条件としての扱い
0
1
2
-1
-100

比較演算や論理演算の結果は、真なら1、偽なら0です。

ただし、条件式には比較結果以外の整数値も指定できます。

if (5) {
    printf("この処理は実行されます。\n");
}

5は0以外なので、条件は真です。

if (-1) {
    printf("この処理も実行されます。\n");
}

-1も0以外なので、条件は真になります。

if (0) {
    printf("この処理は実行されません。\n");
}

0だけが偽として扱われます。

bool型で真偽を表す

stdbool.hを読み込むと、bool型、true、falseを使って真偽を表現できます。

#include <stdbool.h>
bool is_ready = true;
bool has_error = false;

trueは真、falseは偽を表します。

bool型の値は、printfの%dで数値として表示できます。

trueは1
falseは0
システムの利用条件を論理演算子で確認するプログラム

ファイル名:6_7_2.c

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    bool has_permission = true;
    bool system_ready = false;

    printf("[論理積]\n");
    printf("権限があり、システムも準備済み : %d\n",
           has_permission && system_ready);

    printf("\n[論理和]\n");
    printf("権限がある、またはシステムが準備済み : %d\n",
           has_permission || system_ready);

    printf("\n[論理否定]\n");
    printf("権限を持っていない : %d\n",
           !has_permission);

    printf("\ntrueは1、falseは0として表示されます。\n");

    return 0;
}
実行結果の例
[論理積]
権限があり、システムも準備済み : 0

[論理和]
権限がある、またはシステムが準備済み : 1

[論理否定]
権限を持っていない : 0

trueは1、falseは0として表示されます。

論理演算子を確認するプログラムの解説

has_permissionはtrue、system_readyはfalseで初期化しています。

bool has_permission = true;
bool system_ready = false;

数値として考えると、次の状態です。

has_permissionは1
system_readyは0

論理積では、2つの条件を&&で組み合わせています。

has_permission && system_ready

左側は真ですが、右側は偽です。&&は両方が真の場合だけ真になるため、結果は0です。

論理和では、||を使っています。

has_permission || system_ready

has_permissionが真なので、少なくとも一方が真という条件を満たします。そのため、結果は1です。

論理否定では、has_permissionの真偽を反転しています。

!has_permission

has_permissionは真なので、否定した結果は偽を表す0です。

条件式を日本語へ読み替える

条件式は、記号だけを見て考えるよりも、日本語へ読み替えると理解しやすくなります。

条件式日本語での読み方
score == 100scoreは100と等しい
score != 0scoreは0ではない
score >= 60scoreは60以上
score < 0scoreは0より小さい
score <= 100scoreは100以下
(score >= 0) && (score <= 100)scoreは0以上、かつ100以下
is_member || has_ticket会員である、またはチケットを持っている
!is_ready準備できていない
!(a == b)aとbが等しい、ではない

たとえば、次の条件を考えてみましょう。

(score >= 0) && (score <= 100)

この条件は、次のように分けて読めます。

score >= 0
scoreは0以上

score <= 100
scoreは100以下

2つの条件が&&で結ばれているので、式全体は次の意味になります。

scoreは0以上であり、かつ100以下

つまり、scoreが0から100までの範囲内にあるかを判定しています。

括弧を使って条件を読みやすくする

複数の比較式を論理演算子でつなぐときは、それぞれの条件を括弧で囲むと読みやすくなります。

(score >= 0) && (score <= 100)

括弧がなくても同じ意味で動作する場合があります。

score >= 0 && score <= 100

しかし、括弧を付けた方が、どの比較式を&&で組み合わせているのかが分かりやすくなります。

(age >= 20) && is_member

この条件は、年齢が20歳以上という比較結果と、会員かどうかを表すis_memberを組み合わせています。

&&と||を日本語で区別する

&&と||は、必要な条件の数が異なります。

has_card && knows_password

この条件は、カードを持っていて、なおかつパスワードを知っているという意味です。両方を満たす必要があります。

has_card || knows_password

こちらは、カードを持っている、またはパスワードを知っているという意味です。どちらか一方を満たせば真になります。

条件A条件BA && BA || B
0000
0101
1001
1111

図3:==による比較と=による代入の違い

この図から分かること

number == 123は、numberと123の値が等しいかを比較します。

number = 123は比較ではなく、numberへ123を代入します。代入式の値である123は0以外なので、ifでは真として扱われます。

条件式の中で値が等しいかを調べる場合は、==を使う必要があります。

条件式を読むときの確認ポイント

比較や論理演算子を含む式は、次の順番で読むと整理しやすくなります。

  1. それぞれの比較式を日本語へ読み替える
  2. 比較結果が真か偽かを考える
  3. &&なら両方が真か確認する
  4. ||なら少なくとも一方が真か確認する
  5. !があれば真偽を反転する
  6. 最後に式全体の結果を1または0で考える

たとえば、ageが25、is_memberが1の場合を考えてみましょう。

(age >= 20) && is_member
age >= 20は真
is_memberも真
真 && 真
結果は1

is_memberが0なら、次の結果になります。

age >= 20は真
is_memberは偽
真 && 偽
結果は0

条件式を書くときは、次の点にも注意しましょう。

  • 等しいかを比較するときは==を使う
  • =は代入なので比較には使わない
  • 以上は>=、以下は<=と書く
  • =>や=<は使用できない
  • &&は両方が真の場合だけ真になる
  • ||はどちらか一方でも真なら真になる
  • !は真と偽を反転する
  • C言語では0が偽、0以外が真になる
  • 複数の条件は括弧で囲むと読みやすくなる