C言語の基本|条件演算子の使い方

真ならこちら、偽ならあちら。条件演算子を使って、値を選ぶ小さな分岐をすっきり1行で書こう。

C言語で条件分岐を作る代表的な方法はif~else文です。ただし、2つの値からどちらか一方を選ぶだけなら、if~else文では少し大げさに感じることがあります。

たとえば、次のような処理です。

  • 2つの数値から大きいほうを選ぶ
  • 条件に応じて表示メッセージを変える
  • 偶数と奇数で表示する文字を変える
  • 一定の間隔でスペースと改行を切り替える

このような小さな分岐を簡潔に書けるのが条件演算子です。

条件演算子は3つの部分を使うため、三項演算子と呼ばれることもあります。単に処理の流れを分けるのではなく、条件によって値を1つ選び出すところが大きな特徴です。

図1:条件演算子が2つの値から1つを選ぶ流れ

この図から分かること

条件演算子は、最初に条件式を評価します。条件式が真なら式1、偽なら式2が選ばれます。

式1と式2の両方が結果になるわけではありません。選ばれた一方の値だけが、条件演算子全体の評価結果になります。この結果を変数へ代入したり、printfの引数として使用したりできます。

条件演算子の基本構文

条件演算子は、次の形で記述します。

条件式 ? 式1 : 式2

それぞれの部分には、次の役割があります。

部分役割
条件式真か偽かを判定する
?条件式と真の場合の式を区切る
式1条件式が真の場合に選ばれる
:真の場合と偽の場合の式を区切る
式2条件式が偽の場合に選ばれる

読み方は次のとおりです。

  1. 条件式を評価する
  2. 真なら式1を評価する
  3. 偽なら式2を評価する
  4. 選ばれた値を条件演算子全体の結果にする

たとえば、次の式ではleftとrightの小さいほうをminへ代入します。

min = (left <= right) ? left : right;

条件式left <= rightが真ならleft、偽ならrightが選ばれます。その結果が代入演算子=によってminへ格納されます。

条件演算子は値を持つ式

if~elseは条件によって実行する文を分ける制御文です。一方、条件演算子は評価結果を持つ式です。

そのため、次のように代入式の右辺へ書けます。

result = (条件式) ? 値1 : 値2;

関数の引数として使用することもできます。

printf("%s\n", (条件式) ? メッセージ1 : メッセージ2);

条件演算子を読むときは、次の順番に分けると分かりやすくなります。

  • 丸括弧内の条件を読む
  • ?の直後にある真の場合の値を読む
  • :の直後にある偽の場合の値を読む
  • 選ばれた値がどこで使われるかを確認する

if~else文との対応

次の条件演算子では、aとbの大きいほうをmaxに代入します。

max = (a >= b) ? a : b;

同じ処理をif~else文で書くと、次のようになります。

if (a >= b) {
    max = a;
} else {
    max = b;
}

対応関係は次のとおりです。

条件演算子の部分if~else文での対応
a >= bifの条件式
? a条件が真の場合にmaxへ代入する値
: b条件が偽の場合にmaxへ代入する値
条件演算子全体maxへ代入される値

どちらも動作は同じですが、得意な場面が異なります。

書き方得意な処理特徴
if~else条件ごとに複数の文を実行する処理の流れを詳しく書きやすい
条件演算子条件によって1つの値を選ぶ短い分岐を1行で表現しやすい

図2:if~else文と条件演算子の対応

GPT-image-2用プロンプト:

カラーイラスト、16:9横長、アニメ調。日本の電子楽器メーカーにある組み込みソフトウェア開発室で、若い日本人女性C言語プログラマーがif~else文と条件演算子を比較している。画面を左右2つの白いパネルに分ける。左側に「if~else文」と表示し、「a >= bならmax = a」「それ以外ならmax = b」という複数行の分岐を描く。右側に「条件演算子」と表示し、「max = (a >= b) ? a : b;」を1行で大きく描く。両方の下部に「結果:大きいほうをmaxへ代入」と表示する。中央に「同じ結果」「値を選ぶだけなら条件演算子」と日本語で示す。文字は専用パネル内に配置し、人物や背景と重ねない。モニターの背面には文字を入れない。電子ピアノやシンセサイザーを背景にした、明るく見やすいC言語教材イラスト。

この図から分かること

if~else文と条件演算子は、同じ内容の分岐を表現できる場合があります。

条件に応じて代入する値を変えるだけなら、条件演算子を使うと短く書けます。一方、条件ごとに複数の処理を行う場合は、if~else文のほうが処理の内容を追いやすくなります。

条件演算子が向いている場面

条件演算子は、条件によって値を1つ選びたい場面に向いています。

やりたいこと条件演算子の例
大きい値を選ぶmax = (a >= b) ? a : b;
小さい値を選ぶmin = (a <= b) ? a : b;
絶対値に近い変換をするvalue = (n >= 0) ? n : -n;
表示メッセージを選ぶmessage = (ready) ? message1 : message2;
表示する文字を選ぶmark = (n >= 0) ? '+' : '-';
スペースと改行を切り替えるch = (i % 8) ? ' ' : '\n';

共通しているのは、真の場合と偽の場合から、どちらか一方の値を選んでいることです。

テンポに応じてメッセージを切り替える

次のプログラムでは、入力されたテンポが120 BPM以上なら速いテンポ、120 BPM未満なら落ち着いたテンポと表示します。

条件演算子をprintfの引数に使用し、表示する文字列を切り替えます。

テンポに応じたメッセージを1行で選ぶプログラム

ファイル名:8_10_1.c

#include <stdio.h>

int main(void)
{
    int tempo;

    printf("テンポ(BPM)を入力してください > ");
    scanf("%d", &tempo);

    /* 120以上かどうかで表示する文字列を切り替える */
    printf("%s\n",
           (tempo >= 120)
               ? "速いテンポです。"
               : "落ち着いたテンポです。");

    return 0;
}
実行結果の例

140を入力した場合は、条件式が真になります。

テンポ(BPM)を入力してください > 140
速いテンポです。

90を入力した場合は、条件式が偽になります。

テンポ(BPM)を入力してください > 90
落ち着いたテンポです。
プログラムの詳しい解説

入力された整数はtempoに格納されます。

scanf("%d", &tempo);

続くprintfでは、条件演算子によって表示する文字列を選んでいます。

(tempo >= 120)
    ? "速いテンポです。"
    : "落ち着いたテンポです。"

tempoが140の場合、tempo >= 120は真です。そのため、?の後ろにある速いテンポです。が選ばれます。

tempoが90の場合、tempo >= 120は偽です。そのため、:の後ろにある落ち着いたテンポです。が選ばれます。

どちらの結果も文字列なので、printfの変換指定子%sで表示できます。

条件演算子を1行に収めることもできます。

printf("%s\n", (tempo >= 120) ? "速いテンポです。" : "落ち着いたテンポです。");

横に長くなって読みにくい場合は、プログラム例のように複数行へ分けても問題ありません。重要なのは、条件式、真の場合、偽の場合の対応が見やすいことです。

大きい値や小さい値を選ぶ

条件演算子の代表的な使い方が、2つの値から一方を選ぶ処理です。

2つの値から大きいほうを選ぶ場合は、次のように書けます。

max = (first >= second) ? first : second;

first >= secondが真ならfirst、偽ならsecondが選ばれます。

小さいほうを選ぶ場合は、比較の向きを変えます。

min = (first <= second) ? first : second;

このような処理は、真の場合と偽の場合のどちらでも、同じ変数へ異なる値を代入します。そのため、条件演算子と相性のよい書き方です。

printfの表示内容を部分的に切り替える

条件演算子は、printfで表示する内容の一部だけを変更したい場合にも便利です。

たとえば、整数が偶数ならEVEN、奇数ならODDという文字列を選べます。

printf("判定:%s\n",
       (number % 2 == 0) ? "EVEN" : "ODD");

number % 2 == 0が真ならEVEN、偽ならODDが選ばれます。

表示する1文字だけを変更する場合は、文字定数を選ぶこともできます。

printf("符号:%c\n", (number >= 0) ? '+' : '-');

numberが0以上なら+、負なら-が%cで表示されます。

一定間隔でスペースと改行を切り替える

条件演算子を使うと、繰り返し表示の区切り文字も選べます。

(i % 8) ? ' ' : '\n'

この式では、iを8で割った余りによってスペースと改行を切り替えます。

i % 8の値C言語での判定選ばれる文字
0改行
1~7スペース

C言語では0が偽、0以外が真です。そのため、iが8の倍数ならi % 8が0になり、偽の場合の'\n'が選ばれます。

8の倍数でなければ余りが0以外になるため、真の場合の空白文字が選ばれます。

putchar((i % 8) ? ' ' : '\n');

この書き方を繰り返し処理の中で使うと、8個ごとに改行する表示を作れます。

式1と式2はどちらか一方だけ評価される

条件演算子では、式1と式2の両方が評価されるわけではありません。

  • 条件式が真なら式1だけを評価する
  • 条件式が偽なら式2だけを評価する

たとえば、次の条件演算子を考えます。

result = condition ? function_a() : function_b();

conditionが真ならfunction_aだけが呼び出されます。function_bは呼び出されません。

反対にconditionが偽ならfunction_bだけが呼び出され、function_aは呼び出されません。

この性質は便利ですが、代入、インクリメント、関数呼び出しなど、変数や外部の状態を変える処理を式1や式2へ大量に書くと、どちらが実行されるのか追いにくくなります。

式1と式2の型にも注意する

条件演算子では、式1と式2から条件演算子全体の型が決まります。

たとえば、一方がint型でもう一方がdouble型の場合、数値を共通の型として扱うための型変換が行われることがあります。

result = condition ? 10 : 3.5;

この例では、一方が整数の10、もう一方が小数の3.5です。そのため、条件演算子全体はdouble型として扱われ、真の場合の10も10.0に変換されます。

読みやすく予測しやすいコードにするには、式1と式2には同じ種類の値を置くのが基本です。

式1式2分かりやすさ
int型の値int型の値分かりやすい
double型の値double型の値分かりやすい
文字列文字列表示切り替えに向いている
int型の値double型の値型変換に注意が必要
数値文字列目的を見直したほうがよい

図3:条件演算子を安全に使う3つのポイント

この図から分かること

条件演算子では、条件式に応じて式1または式2の一方だけが評価されます。また、選択する2つの値の型が異なる場合は、意図しない型変換が起きないか確認する必要があります。

条件演算子を何段も重ねることはできますが、条件と値の対応が追いにくくなります。短く単純な値の選択に使うことが、読みやすさを保つポイントです。

条件演算子のネストは控えめにする

条件演算子の式1や式2に、さらに条件演算子を書くこともできます。

result = condition1
             ? value1
             : condition2
                   ? value2
                   : value3;

この形は3つの値から選べますが、どの条件がどの値に対応しているのか分かりにくくなります。

書き方向いている場面
1段の条件演算子2つの値から一方を選ぶ
ネストした条件演算子ごく短く、対応が明確な値の選択
if~else if~else3つ以上の分岐や複雑な処理

複数段の分岐が必要なら、if~else if~elseを使ったほうが条件の順番や処理範囲を確認しやすくなります。

条件演算子とif~else文を使い分ける

条件演算子は、短く書くことだけを目的に使うものではありません。条件によって値を選ぶという意図を明確にするための演算子です。

次のような場合は条件演算子が向いています。

  • 真と偽で選ぶ値が1つずつある
  • 選んだ値を変数へ代入する
  • printfへ渡す表示内容を変える
  • 条件式と2つの値が短く読みやすい

次のような場合はif~else文のほうが向いています。

  • 条件ごとに複数の文を実行する
  • 変数の更新や関数呼び出しが多い
  • 3つ以上の分岐がある
  • 条件演算子を複数段重ねないと書けない
  • 1行にすると式が長くなりすぎる

短く書けるかどうかだけで判断せず、条件と選ばれる値の関係がひと目で分かる場合に条件演算子を使うと、すっきりしたコードになります。