閉じる

C言語の条件演算子(三項演算子)とは?if文を1行で書く基本

短い分岐なら条件演算子(三項演算子)を使うとif文を1行にまとめられます

C言語では条件 ? 真の式 : 偽の式という書き方で、式として値を返すのが特徴です。

この記事では、基本の構文からif文の書き換え、実用例、注意点まで、初心者向けに丁寧に解説します。

条件演算子(三項演算子)の基本

条件演算子とは?if文を1行にする仕組み

条件演算子はifelseで書く単純な二択の分岐を1行の式として表現できます。

次の2つは意味が同じです。

C言語
// if-else での分岐
int x;
if (a > b) {
    x = a;
} else {
    x = b;
}

// 条件演算子での分岐 (同じ意味)
int y = (a > b) ? a : b;

ポイントは「式である」ことです。

代入やreturnの右辺に直接書けるため、短い分岐にはとても相性が良いです。

構文: 条件 ? 真の式 : 偽の式

書式は次の通りです。

  • 条件 ? 真の式 : 偽の式

条件が真(非0)なら真の式が評価され、その値が結果になります。

偽(0)なら偽の式が評価されます。

なお、真の式偽の式どちらか一方しか評価されません

次の表で各部の役割を整理します。

部分役割補足
条件判定したい式0なら偽、0以外なら真
真の式条件が真のときの値(式)評価されるのは真のときのみ
偽の式条件が偽のときの値(式)評価されるのは偽のときのみ

値を返す式として使える

条件演算子は「値を返す式」なので、代入や関数の引数、returnの右辺にそのまま書けます。

型は両方の式の型が両立するように決まります(整数同士、浮動小数同士、互換のポインタ同士、など)。

C言語
// 代入
int max = (a > b) ? a : b;

// 引数の中で
printf("%s\n", (n % 2 == 0) ? "even" : "odd");

// return の中で
return (score >= 60) ? PASS : FAIL;

両側の式に副作用(インクリメントやファイル書き込みなど)を詰め込むのは避けましょう

読みづらく、デバッグも難しくなります。

1行のメリットと向き不向き

短い分岐を1行で書けるのが最大の利点です。

コードがコンパクトになり、視線の移動も少なくなります。

一方で、長い処理や多段の条件には向きません

可読性が下がるため、その場合は素直にifに戻すのがよいです。

次のように考えると判断しやすくなります。

使うべき場面避けるべき場面
値を選んで代入・返却・表示するだけ複数行にわたる処理、複数の副作用
短いメッセージ切替や数値の二択条件が複雑(複数の論理演算を含む)
1回の選択で済む場面ネストして三択以上にしたくなる場面

if文から三項演算子への書き換え

if-elseの基本を三項演算子で表現

基本形は次の対応になります。

右辺に結果が現れるのが肝心です。

C言語
// if-else 版
int result;
if (ok) {
    result = 1;
} else {
    result = 0;
}

// 三項演算子版
int result2 = ok ? 1 : 0;

置き換えの考え方

  • 「変数 = …」の形にできる分岐は置き換えやすいです。
  • 「実行する処理が2種類ある」だけのときは、無理に置き換えない方が読みやすいことが多いです。

代入の省略: a = 条件 ? X : Y

よくある書き方はa = (条件) ? X : Y;です。

二者択一で値を選ぶ場面に最適です。

C言語
// a と b のうち小さい方を min に代入
int min = (a < b) ? a : b;

returnで使う書き方

関数から返す値を切り替えるときにも簡潔です。

早期returnで分岐を畳めるので、ネストが浅くなります。

C言語
// 偶奇で文字列を返す
const char* even_or_odd(int n) {
    return (n % 2 == 0) ? "偶数" : "奇数";
}

短い条件だけに使うのがコツ

三項演算子のネストは読みづらさの元です。

例えばn > 0 ? "正" : n == 0 ? "ゼロ" : "負"のような書き方は、if-else if-elseに展開した方が明確です。

使い方の例

正負の判定を1行で

0以上かどうかをメッセージで切り替えます。

C言語
#include <stdio.h>

int main(void) {
    int xs[] = {-5, 0, 7};
    int n = (int)(sizeof(xs) / sizeof(xs[0]));

    for (int i = 0; i < n; i++) {
        int x = xs[i];
        // 条件が真なら「非負(0以上)」、偽なら「負」
        printf("%d は%sです\n", x, (x >= 0) ? "非負(0以上)" : "負");
    }
    return 0;
}
実行結果
-5 は負です
0 は非負(0以上)です
7 は非負(0以上)です

合格判定のメッセージ切り替え

点数scoreが60以上なら合格、そうでなければ不合格と表示します。

C言語
#include <stdio.h>

int main(void) {
    int scores[] = {30, 60, 85};
    int n = (int)(sizeof(scores) / sizeof(scores[0]));

    for (int i = 0; i < n; i++) {
        int score = scores[i];
        const char* msg = (score >= 60) ? "合格" : "不合格";
        printf("%3d 点: %s\n", score, msg);
    }
    return 0;
}
実行結果
 30 点: 不合格
 60 点: 合格
 85 点: 合格

最小値(小さい方)を選ぶ

二つの整数abの小さい方を選びます。

C言語
#include <stdio.h>

int main(void) {
    int a = 10;
    int b = 4;
    int min = (a < b) ? a : b;  // 真なら a、偽なら b
    printf("min(%d, %d) = %d\n", a, b, min);
    return 0;
}
実行結果
min(10, 4) = 4

真偽フラグで文字を選ぶ

boolのフラグからシンプルに1文字を選びます。

C言語
#include <stdio.h>
#include <stdbool.h> // bool, true, false を使う

int main(void) {
    bool enabled = true;
    char mark = enabled ? 'Y' : 'N';  // 有効なら 'Y'、無効なら 'N'
    printf("enabled=%s => mark=%c\n", enabled ? "true" : "false", mark);

    enabled = false;
    mark = enabled ? 'Y' : 'N';
    printf("enabled=%s => mark=%c\n", enabled ? "true" : "false", mark);
    return 0;
}
実行結果
enabled=true => mark=Y
enabled=false => mark=N

printfで出力を切り替える

1回のprintfで文字列だけを切り替えるのが読みやすいです。

C言語
#include <stdio.h>

int main(void) {
    int n1 = 3;
    int n2 = 8;

    // おすすめ: 書式は固定、%s の中身だけを切り替える
    printf("n1=%d は %s です\n", n1, (n1 % 2 == 0) ? "偶数" : "奇数");

    // こう書くことも可能だが、呼び出しが2つに分かれて読みづらい
    (n2 % 2 == 0) ? puts("n2 は偶数です") : puts("n2 は奇数です");

    return 0;
}
実行結果
n1=3 は 奇数 です
n2 は偶数です

注意点と読みやすい書き方

ネスト(入れ子)は避ける

三択以上を三項演算子でつなぐと一気に読みにくくなります

次のような書き方は避けましょう。

C言語
// 読みにくい例: 三項演算子のネスト
// const char* label = (n > 0) ? "正" : (n == 0) ? "ゼロ" : "負";

// 代わりに if-else if-else で明確に
const char* label_of(int n) {
    if (n > 0) {
        return "正";
    } else if (n == 0) {
        return "ゼロ";
    } else {
        return "負";
    }
}

長い処理はif文を使う

分岐ごとに複数行の処理がある場合、三項演算子に押し込めると可読性を損ないます。

ログ出力→計算→代入のような流れは素直にif-elseへ。

条件演算子は「値を選ぶ」場面専用と考えるのが安全です。

条件と結果は短くシンプルに

条件式は1つか2つの比較にとどめ、結果も定数・変数・短い式に留めると読みやすくなります。

冗長になりそうなら、途中の結果を一旦変数に入れてから使いましょう。

C言語
// 悪い例: 長い計算をそのまま詰め込む
// price = is_vip ? base * (1.0 - (coupon_rate * seasonal_rate)) : base;

// 良い例: 中間値を分けて見通しを良くする
double discount = coupon_rate * seasonal_rate;
price = is_vip ? base * (1.0 - discount) : base;

括弧で意図をはっきり書く

括弧で区切ると誤読を防げます

特に結果側が演算式のときは括弧で包むのが無難です。

C言語
// 括弧で意図を明確に
int result = (cond) ? (x + y) : (x - y);

演算子の優先順位に注意

条件演算子?:多くの演算子より優先順位が低い一方で、=(代入)よりは高いです。

また?:右結合(右から結びつく)です。

迷ったら必ず括弧で明示しましょう。

以下の小さなプログラムは、同じ見た目でも括弧がないと全く違う意味になる例です。

C言語
#include <stdio.h>

int main(void) {
    int a = 1, b = 2;

    // 優先順位: + が ?: より高いので、(a + b) ? 10 : 20 と解釈される
    int r1 = a + b ? 10 : 20;      // (1 + 2) は真 → 10

    // 括弧で ?: を先に評価させる
    int r2 = a + (b ? 10 : 20);    // b は 2 で真 → 10、よって 1 + 10 = 11

    printf("r1=%d, r2=%d\n", r1, r2);

    // ?: は右結合。a ? b : c ? 100 : 200 は a ? b : (c ? 100 : 200)
    int a0 = 0, c = 2;
    int x = a0 ? b : c ? 100 : 200; // a0 が偽 → (c ? 100 : 200) → 100
    printf("x=%d\n", x);

    // 代入より ?: の方が強く結びつく
    int m, n = 5;
    m = (n % 2 == 0) ? 100 : 200;   // 実際の解釈は m = ((n % 2 == 0) ? 100 : 200)
    printf("m=%d\n", m);

    return 0;
}
実行結果
r1=10, r2=11
x=100
m=200

評価順序にも注意が必要です。

条件式が先に評価され、真か偽かでどちらか一方の式だけが評価されます。

したがって、次のような副作用を両側に書くと読みにくく、バグの温床です。

C言語
// 推奨しない: 両側に副作用がある例 (片方しか呼ばれないが読み手を惑わせる)
(cond) ? do_side_effect_A() : do_side_effect_B();

副作用を伴う処理if-elseに戻しましょう。

まとめ

条件演算子?:「値の二択」を1行で書ける強力な道具です。

構文は条件 ? 真の式 : 偽の式で、代入・関数引数・returnの右辺として活躍します。

読みやすさを保つコツは、短い条件・短い結果だけに使うこと、ネストや副作用は避けること、そして迷ったら括弧で明示することです。

向き不向きを見極めて、if文と三項演算子を使い分けできるようになれば、コードはより簡潔で意図が伝わりやすくなります。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!