C言語では条件分岐を行うためにif文を使うことが多いですが、より簡潔に書きたいときに便利なのが条件演算子(三項演算子)です。
1行で条件分岐による値の選択ができ、処理の意図がはっきりしている場面ではコードが読みやすくなります。
本記事では、C言語初心者の方に向けて、条件演算子の基本から、if文との違い、注意点、実務的な使い分けのコツまで丁寧に解説します。
C言語の条件演算子(三項演算子)とは
条件演算子(三項演算子)の基本構文と意味
条件演算子は、次のような3つの部分から構成される演算子です。
演算子を3つのオペランドで使うので三項演算子と呼ばれます。
基本構文
条件式 ? 式1 : 式2 という形で書きます。
条件式
真(0以外)か偽(0)かを判定する式です。式1
条件式が真のときに評価される式です。式2
条件式が偽のときに評価される式です。
条件式が真なら式1の値、偽なら式2の値が結果として返る、というのが条件演算子の基本的な動作です。
単純な使用例
次の例では、整数aが0以上かどうかで文字列を切り替えています。
#include <stdio.h>
int main(void) {
int a = 5;
// 条件演算子でメッセージを切り替える
const char *msg = (a >= 0) ? "aは0以上です" : "aは負です";
printf("%s\n", msg);
return 0;
}
このプログラムでは、(a >= 0)が真なので"aは0以上です"が選ばれます。
aは0以上です
if文との違いと共通点
共通点
if文と条件演算子は、どちらも「条件によって処理を分ける」ために使います。
例えば、次の2つのコードは意味としては同じです。
// if文の場合
if (a > b) {
max = a;
} else {
max = b;
}
// 条件演算子の場合
max = (a > b) ? a : b;
どちらも「aがbより大きければaを、そうでなければbをmaxに代入する」という処理を行っています。
違い
ただし、性質にはいくつか重要な違いがあります。
1つ目は「式か文か」という違いです。
- 条件演算子は式です。値を返します。
- if文は文です。値を返しません。
2つ目として、表現できる処理の幅にも違いがあります。
- if文はブロック
{ }の中に複数の文を書けるので、
複雑な処理や複数行の処理に向いています。 - 条件演算子は1つの式として評価されるため、
基本的には「どちらか一方の値を選ぶ」用途に向きます。
C言語で条件演算子を使うメリット・デメリット
メリット
条件演算子には、次のようなメリットがあります。
- コードを1行にまとめやすい
if文で3〜4行書くような処理を、1行で書けることがあります。 - 「条件によって値を選ぶ」意図を明確にできる
代入や関数の引数の中で直接使えるので、
「この値は条件で切り替えている」とすぐに分かります。 - 式として使えるため関数呼び出しの引数やreturn文に直接書けます。
デメリット
一方で、注意すべき点もあります。
- 複雑になると非常に読みにくい
ネストや長い式を条件演算子で書くと、処理の意図が分かりづらくなります。 - 優先順位やカッコの付け方を間違えると、思わぬバグを生みます。
- if文に比べてデバッグしにくい場合があります。
途中経過をprintfなどで確認しにくいからです。
「簡潔さ」と「読みやすさ」のバランスを取ることが、条件演算子をうまく使うポイントです。
条件演算子でif文を1行に書く基本パターン
条件によって値を切り替える三項演算子の書き方
条件演算子の典型的な使い方は、「条件によって選ぶ値を変える」というパターンです。
最小値・最大値を選ぶ例
#include <stdio.h>
int main(void) {
int a = 10;
int b = 20;
// 条件演算子で最大値を選ぶ
int max = (a > b) ? a : b;
// 条件演算子で最小値を選ぶ
int min = (a < b) ? a : b;
printf("max = %d\n", max);
printf("min = %d\n", min);
return 0;
}
max = 20
min = 10
このようにmaxやminを求める場面では、条件演算子が非常にすっきり書けます。
変数への代入をif文から条件演算子に書き換える例
if文の書き方
まずは、if文で書いた場合を確認します。
#include <stdio.h>
int main(void) {
int x = 7;
int y;
// if文でyの値を決める
if (x % 2 == 0) {
y = 0; // 偶数なら0
} else {
y = 1; // 奇数なら1
}
printf("y = %d\n", y);
return 0;
}
y = 1
条件演算子で1行にまとめる
上の処理は、次のように1行で書くことができます。
#include <stdio.h>
int main(void) {
int x = 7;
// 条件演算子でyの値を決める
int y = (x % 2 == 0) ? 0 : 1;
printf("y = %d\n", y);
return 0;
}
y = 1
ここでは「yはxが偶数なら0、奇数なら1」というシンプルな関係があり、条件演算子を使うことで意図がはっきりした短いコードになっています。
printfと条件演算子を組み合わせた1行の書き方
メッセージだけを切り替えたいような場面では、printfと条件演算子を組み合わせると便利です。
if文で書く場合
#include <stdio.h>
int main(void) {
int score = 80;
if (score >= 60) {
printf("合格です\n");
} else {
printf("不合格です\n");
}
return 0;
}
合格です
条件演算子で1行に書く場合
#include <stdio.h>
int main(void) {
int score = 80;
// printfの引数として条件演算子を使う
printf("%s\n", (score >= 60) ? "合格です" : "不合格です");
return 0;
}
合格です
このように、出力する文字列だけが条件で変わる場合は、条件演算子を使うと簡潔に書けます。
ネストしたif文を条件演算子で書くときの考え方
ネストとは、if文の中にさらにif文が入っているような構造のことです。
条件演算子もネストして書くことができますが、読みやすさを大きく損なう可能性があるため、使い方には注意が必要です。
ネストしたif文の例
例えば、点数から評価を文字で表す場合を考えます。
#include <stdio.h>
int main(void) {
int score = 85;
const char *grade;
if (score >= 80) {
grade = "A";
} else if (score >= 70) {
grade = "B";
} else if (score >= 60) {
grade = "C";
} else {
grade = "D";
}
printf("評価: %s\n", grade);
return 0;
}
評価: A
条件演算子でネストして書く例
同じ処理を条件演算子で書くと次のようになります。
#include <stdio.h>
int main(void) {
int score = 85;
// ネストした条件演算子で評価を決める
const char *grade =
(score >= 80) ? "A" :
(score >= 70) ? "B" :
(score >= 60) ? "C" :
"D";
printf("評価: %s\n", grade);
return 0;
}
評価: A
書き方のポイントは次の通りです。
- インデントをしっかり付けて、階層を視覚的に分かりやすくすること。
- 条件の順番をif文と同じように「上から順に判定していく」イメージで並べること。
- ネストが深くなりすぎたらif文に戻すことを検討すること。
ネストした条件演算子は短く書ける反面、ミスに気付きにくいので、初心者の方は特に慎重に使う必要があります。
C言語初心者が注意したい条件演算子の落とし穴
条件演算子と代入演算子(=)の書き間違いに注意
C言語初心者がよくするミスの1つに、比較演算子==と代入演算子=の書き間違いがあります。
これはif文でも起こりますが、条件演算子でも同様です。
間違った例
#include <stdio.h>
int main(void) {
int x = 5;
// 間違った比較: x == 0 と書くべきところを x = 0 と書いてしまった例
const char *msg = (x = 0) ? "ゼロではない" : "ゼロ";
printf("%s\n", msg);
printf("x = %d\n", x); // xの値も確認
return 0;
}
ゼロ
x = 0
ここではx = 0が実行され、xに0が代入されています。
その結果(x = 0)の評価値は0となり、条件は偽として扱われ"ゼロ"が選ばれます。
さらに、意図せずxの値まで変わってしまうという危険なバグになります。
正しい例
#include <stdio.h>
int main(void) {
int x = 5;
// 正しい比較: x == 0
const char *msg = (x == 0) ? "ゼロ" : "ゼロではない";
printf("%s\n", msg);
printf("x = %d\n", x);
return 0;
}
ゼロではない
x = 5
条件式を書くときは「= が1つか2つか」を必ず確認し、比較なら==を使うことを意識してください。
三項演算子のネストで読みづらくなるケース
条件演算子は便利ですが、ネストが深くなると一気に可読性が下がります。
読みにくい例
#include <stdio.h>
int main(void) {
int n = 15;
// 非常に読みにくいネストした条件演算子
const char *msg =
(n % 3 == 0) ? ((n % 5 == 0) ? "3と5の倍数" : "3の倍数")
: ((n % 5 == 0) ? "5の倍数" : "その他");
printf("%s\n", msg);
return 0;
}
3と5の倍数
意味としては「nが3の倍数かつ5の倍数かどうか」を判定していますが、括弧と?と:が入り乱れて非常に読みにくいコードになっています。
このような場合は、素直にif文で書き直した方がよいことが多いです。
if文で書き直した例
#include <stdio.h>
int main(void) {
int n = 15;
const char *msg;
if (n % 3 == 0 && n % 5 == 0) {
msg = "3と5の倍数";
} else if (n % 3 == 0) {
msg = "3の倍数";
} else if (n % 5 == 0) {
msg = "5の倍数";
} else {
msg = "その他";
}
printf("%s\n", msg);
return 0;
}
3と5の倍数
処理内容が増えてきたら、「無理に条件演算子で1行に詰め込まない」ことが大切です。
優先順位とカッコの付け方で起こるバグ
C言語では、演算子には優先順位があります。
条件演算子?:はやや特殊な優先順位を持っているため、カッコを省略すると意図しない評価順になることがあります。
注意したいコード例
#include <stdio.h>
int main(void) {
int a = 1;
int b = 2;
int c = 3;
// 一見すると (a ? b : c) + 1 に見えるかもしれないが…
int result = a ? b : c + 1;
printf("result = %d\n", result);
return 0;
}
result = 2
このコードは、優先順位のルールによりa ? b : (c + 1)として解釈されます。
したがって、aが真(1)なのでbが選ばれ、resultは2になります。
「条件演算子全体に+1をしたかったのに、そうなっていない」といったバグが起こりやすいパターンです。
意図を明確にする書き方
評価順を明確にするために、カッコを積極的に使うことが重要です。
// 条件で選んだ値に+1したいとき
int result = (a ? b : c) + 1;
// c + 1 か b を選びたいとき
int result2 = a ? b : (c + 1);
条件演算子を含む式では、少し多いくらいにカッコを付ける方が、初心者のうちは安全です。
戻り値の型が異なるときの暗黙の型変換に注意
条件演算子は「1つの式として1つの型の値を返す」必要があります。
そのため、式1と式2の型が異なると、どちらかに自動変換されることがあります。
型が異なる例
#include <stdio.h>
int main(void) {
int flag = 1;
// 片方はint、片方はdouble
double value = flag ? 1 : 2.5;
printf("value = %f\n", value);
return 0;
}
value = 1.000000
この場合、1はint型、2.5はdouble型です。
C言語では、より「広い」型に合わせるルールがあるため、1がdouble型の1.0に変換されます。
結果として、式全体の型はdouble型になります。
意図しない丸めや情報損失の例
#include <stdio.h>
int main(void) {
int flag = 0;
// doubleかintかで情報量が変わる
int result = flag ? 3.7 : 2;
printf("result = %d\n", result);
return 0;
}
result = 2
ここでは、条件演算子の結果はint型になります。
そのため、3.7は3に切り捨てられてから扱われます。
条件演算子の両側の型は、できるだけ揃えることを意識し、異なる場合は明示的なキャストや、変数の型を見直すことをおすすめします。
条件演算子とif文の使い分けのコツ
「? :」が向いているシンプルな条件分岐
条件演算子が特に向いているのは、「条件によって選ぶ値が1つだけ」のシンプルな場面です。
例えば次のような用途です。
- 最小値・最大値を求めるとき
- 正負の符号を決めるとき
- メッセージやラベルを切り替えるとき
- return文の中で値を切り替えるとき
例: return文での使用
#include <stdio.h>
// 正の数なら1、負の数なら-1、0なら0を返す関数
int sign(int x) {
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
int main(void) {
printf("sign(10) = %d\n", sign(10));
printf("sign(-5) = %d\n", sign(-5));
printf("sign(0) = %d\n", sign(0));
return 0;
}
sign(10) = 1
sign(-5) = -1
sign(0) = 0
このように、「最終的に返したい値」を1行で表現したいときには、条件演算子がよく使われます。
ただし、ネストが深くなりすぎないように注意が必要です。
読みやすさ重視でif文を選ぶべき場面
次のような場合は、条件演算子ではなくif文を使う方が読みやすく、安全です。
- ブロックの中に複数の文が必要なとき
(変数の代入だけでなく、printfや他の関数呼び出しなどがある場合) - 条件が複雑で、かつネストが深いとき
- バグが起きやすい重要な処理で、後から読む人にとっての分かりやすさが特に重要なとき
- 条件によって処理の流れが大きく変わるとき
if文を選ぶべき例
#include <stdio.h>
int main(void) {
int score = 75;
if (score >= 80) {
printf("評価: A\n");
printf("よくできました\n");
} else if (score >= 70) {
printf("評価: B\n");
printf("まずまずです\n");
} else if (score >= 60) {
printf("評価: C\n");
printf("合格です\n");
} else {
printf("評価: D\n");
printf("再チャレンジしましょう\n");
}
return 0;
}
メッセージを複数行出力しているようなケースを、無理に条件演算子に詰め込むと、かえって読みにくくバグを生みやすいコードになります。
条件演算子を使うときのスタイルガイドと実践的な書き方
条件演算子を安全かつ読みやすく使うための実践的なルールをいくつか紹介します。
1. 1つの式に収まるシンプルな場面に限定する
「値を1つ選ぶだけ」という場面に限定すると、条件演算子の利点を活かしつつ、複雑化を防げます。
// OK: 値を選んで代入するだけ
min = (a < b) ? a : b;
2. ネストが必要になったらレイアウトに気を付ける
ネストを使う場合は、次のように改行とインデントを使うことで多少読みやすくできます。
const char *grade =
(score >= 80) ? "A" :
(score >= 70) ? "B" :
(score >= 60) ? "C" :
"D";
それでも読みにくいと思ったら、素直にif文に戻す判断も大切です。
3. カッコを積極的に使う
優先順位によるバグを防ぐため、条件式や全体の式をカッコで囲む習慣を付けると安全です。
int result = (a > b) ? a : b;
int adjusted = (a > b) ? (a + 10) : (b + 10);
4. 代入と比較を混ぜない
条件演算子の中に代入や副作用のある処理を入れすぎると、挙動が分かりにくくなります。
初心者のうちは、条件式は比較と論理演算に限定するくらいの意識で書くとよいです。
// なるべくこう書く
const char *msg = (x == 0) ? "ゼロ" : "ゼロではない";
// こういった書き方は避ける (読みにくく、バグの元になりやすい)
const char *msg = (x = calc()) ? "OK" : "NG";
5. チームや教科書のスタイルに合わせる
実務では、プロジェクトやチームごとにスタイルガイドが決められていることがあります。
学校の授業でも、教科書や先生の方針によっては「条件演算子は最低限に」とされることもあります。
初心者のうちは、まずはif文で正しく書けるようになることを優先し、そのうえで「ここは条件演算子にするとすっきりするな」と感じる箇所から少しずつ使い始めるとよいでしょう。
まとめ
条件演算子(三項演算子)は、「条件によって選ぶ値が1つだけ」の場面でif文よりも簡潔に書ける便利な機能です。
特に、代入やprintf、return文で値を切り替える用途に向いています。
一方で、ネストや複雑な式になると一気に読みにくくなり、優先順位や型変換の落とし穴でバグを生みやすくなります。
初心者の方は、まずif文で正しいロジックを書けるようにし、そのうえで単純なパターンから条件演算子を取り入れ、「簡潔さ」と「読みやすさ」のバランスを意識して使い分けていくことをおすすめします。
