🇯🇵 日本語 | 🇺🇸 English

第14回 確認問題(if)

C言語のif文の理解度を確認するクイズ。

🎬
この講座を動画で見る(約8分)
スライド解説 + 音声ナレーション

確認問題1 ― if(a==10) の動作

int a = 10;
if (a == 10) {
  printf("Aです\n");
  a = 20;
}
printf("a = %d\n", a);

出力結果は?

Aです
a = 20
Aです
a = 10
a = 20
解説: a==10 は真 → if内を実行 → "Aです" 表示 → aを20に上書き → 最後に a=%d でaの現在値(20)を表示。

確認問題2 ― if(a=10) の落とし穴

int a = 3;
if (a = 10) {    // = は代入! (== の誤り)
  printf("入った\n");
}
printf("a = %d\n", a);

出力結果は?

a = 3 (ifに入らない)
入った
a = 10
コンパイルエラー
解説: a = 10代入式で、その値は10(非ゼロ=真)。よってif内が実行されます。さらに、a自体が10に書き換わっているため、最後の出力は a = 10
Cはこれをエラーにせず、警告だけ出すことも。意図せぬバグの温床です。

確認問題3 ― AND/OR の組み合わせ

int x = 5;
if (x > 0 && x < 10 || x == 100) {
  printf("OK\n");
}

出力結果は?

OK
(何も出力されない)
コンパイルエラー
解説: &&|| より優先されるので、実質 (x>0 && x<10) || x==100
x=5 のとき、(5>0 && 5<10) = 真 → 全体も真 → "OK" を表示。
優先順位が曖昧なときは必ずカッコを使って明示しましょう。

確認問題4 ― if-else の基本

int n = 7;
if (n > 5) {
  printf("大きい\n");
} else {
  printf("小さい\n");
}

出力結果は?

大きい
小さい
大きい
小さい(両方)
(何も出力されない)
解説: if の条件が真なら if ブロック、偽なら else ブロックのどちらか一方だけが実行されます。
n=7 は n > 5 が真 → "大きい" が表示、else は実行されない。

確認問題5 ― else if ラダー

複数の条件を順に調べるパターン。最初に真になった枝だけが実行されます。
int score = 75;
if (score >= 90) {
  printf("A\n");
} else if (score >= 70) {
  printf("B\n");
} else if (score >= 50) {
  printf("C\n");
} else {
  printf("D\n");
}

出力結果は?

A
B
C
B
C(両方マッチ)
解説: else if ラダーでは、最初に真になった枝で終了します。
score=75 は 90 以上ではない → 次の >=70 が真 → "B" を表示 → それ以降の条件は調べない
条件は 重なっていてもOK(上から順に評価されるので、厳しい条件を先に書くのがセオリー)。

確認問題6 ― 中括弧なしの if(罠)

中括弧 { } を省略したとき、if の「範囲」はどこまで?
int a = 5;
if (a > 10)
  printf("big\n");
  printf("always\n");   // ←見た目インデントに注意!

出力結果は?

always (1行だけ)
(何も出力されない)
big
always
big
解説: 中括弧がない if は、直後の1文だけを条件付きで実行します。
a=5 で条件は偽 → printf("big"); はスキップ。
2つ目の printf("always"); は if の外なので常に実行され、"always" が表示されます(インデントに騙されない!)。
教訓: if の中身が1文でも、中括弧を書く習慣をつけましょう。2文目を後から足してもバグを生みません。

確認問題7 ― 浮動小数の == 比較

数学的には 0.1 + 0.2 = 0.3。C言語ではどうでしょう?
double x = 0.1 + 0.2;
if (x == 0.3) {
  printf("等しい\n");
} else {
  printf("等しくない\n");
}

出力結果は?

等しい
等しくない
コンパイルエラー
解説: コンピュータの浮動小数点は 2 進数で数値を保持するため、0.1 や 0.2 は完全には表現できない
0.1 + 0.2 の実際の値は 0.30000000000000004... となり、0.3 とは厳密には一致しません。結果: 等しくない
教訓: double 型の == は避け、差の絶対値が小さければ等しいとみなすのが定石(例: fabs(x - 0.3) < 1e-9)。

確認問題8 ― 短絡評価(ゼロ除算ガード)

&& の左側が偽なら、右側は評価されない。これでゼロ除算を防げるか?
int a = 10, b = 0;
if (b != 0 && a / b > 5) {
  printf("OK\n");
} else {
  printf("スキップ\n");
}

何が起こる?

OK が表示される
スキップ が表示される(ゼロ除算は起きない)
ゼロ除算エラーで異常終了
コンパイルエラー
解説: &&短絡評価(short-circuit)を行います。左側 b != 0偽の時点で、右側 a / b は評価されない
したがってゼロ除算は起きず、else の "スキップ" が表示されます。
活用パターン: 「安全性チェック && 本体の条件」のようにガード節として書くと、エラーを未然に防げます。
※ 順番を逆にして a / b > 5 && b != 0 と書くと、先に除算が行われてゼロ除算になります。安全な条件を先に

確認問題9 ― else なしで全部外れると?

if / else if だけで else を省略したとき、どの条件も真でなければ?
int x = 100;
if (x < 0) {
  printf("負\n");
} else if (x < 10) {
  printf("小\n");
} else if (x < 50) {
  printf("中\n");
}
printf("終わり\n");

出力結果は?


終わり
終わり
(何も出力されない)
コンパイルエラー
解説: x=100 はどの条件(<0, <10, <50)にも当てはまらない。else が無いので、if ブロックは何もせずに素通りします。
その後の printf("終わり"); は if の外にあるので、当然実行され "終わり" だけが出力されます。
教訓: 「該当なし」の処理が必要なら else を書く。else を省けば「該当しなければ何もしない」という意味。

確認問題10 ― 独立した if と else if の違い

見た目は似ていても動きが違う。次の2つのコードを比較。
// パターンA: else if でつなぐ
int n = 50;
if (n > 0) {
  printf("正\n");
} else if (n > 30) {
  printf("大\n");
}

// パターンB: 独立した if を2つ並べる
if (n > 0) {
  printf("正\n");
}
if (n > 30) {
  printf("大\n");
}

それぞれ n=50 のとき出力は?

A: 正
B: 正
A: 正 / B: 正
A: 正
大 / B: 正
A: 正
大 / B: 正
解説: これが else if と独立した if の決定的な違い。
パターンA (else if): 最初に真になった枝だけ実行。n=50 は n>0 で真 → "正" を表示して終了(n>30 はもう見ない)。
パターンB (独立した if 2つ): それぞれ独立して評価される。n>0 が真 → "正"、続けて n>30 も真 → "大" と両方表示。
使い分け: 「ひとつだけ実行したい」→ else if。「独立に両方チェックしたい」→ 独立した if を並べる。

確認問題11 ― 最後の else は「キャッチオール」

else if ラダーの最後の else は、それまでの条件が全部外れたとき必ず実行される。
int grade = -5;
if (grade >= 90) {
  printf("秀\n");
} else if (grade >= 70) {
  printf("優\n");
} else if (grade >= 50) {
  printf("可\n");
} else {
  printf("不可\n");
}

grade=-5(負の値)のときの出力は?

(何も出力されない)
不可
解説: -5 は >=90>=70>=50 もすべて偽。最後の else に到達するので "不可" が表示される。
最後の else は「どの条件にも当てはまらなかった全ケース」を受け止めるキャッチオールです。
教訓: 予期しない値(-5 や 999 など)が来ても必ずどこかの枝で処理される、という安心感のために else を書いておくのがおすすめ。

確認問題12 ― dangling else(else はどこに?)

中括弧を省略した else。どちらの if にくっつくでしょうか?
int a = 5, b = 10;
if (a > 0)
  if (b > 20)
    printf("両方大\n");
  else
    printf("bは小\n");

出力結果は?(インデントは関係ありません)

両方大
bは小
(何も出力されない)
コンパイルエラー
解説: else は一番近い if にくっつくルール(dangling else ルール)。
コードの見た目のインデントは「外側の if の else」のように見えますが、実際には内側の if (b > 20) の else として解釈されます。
a=5(a > 0 真)→ 内側の if に入る → b=10 なので b > 20 は偽 → else "bは小" が表示される。
教訓: ネストした if では必ず中括弧を書くこと。曖昧さを完全に消せます。

確認問題13 ― 成績判定バグ(if 複数 vs else if)

成績を A / B / C に分けたい。よくあるバグの典型例を見てみましょう。
// ❌ バグのあるコード: 独立した if を3つ並べた
int score = 85;
if (score >= 90) {
  printf("A\n");
}
if (score >= 70) {
  printf("B\n");
}
if (score >= 50) {
  printf("C\n");
}

score=85 のときの出力は?

A
B
B
C
A
B
C
解説: 独立した if が3つ並んでいるので、条件を満たしたすべてのブロックが実行されます。
score=85 は: >=90 は偽 → スキップ/ >=70 は真 → "B" 表示/ >=50 も真 → "C" 表示。結果: B と C が両方出る

🔧 正しい書き方(else if を使う):
if (score >= 90) {
  printf("A\n");
} else if (score >= 70) {
  printf("B\n");
} else if (score >= 50) {
  printf("C\n");
}
こうすれば else if チェーンの最初に真になった枝だけが実行され、score=85 では "B" のみ表示されます。

判断基準:
  • 条件が互いに排他的(どれか1つだけ)→ else if を使う
  • 条件が独立(両方真になりうる、両方処理したい)→ 独立した if を並べる

関連する講座

条件分岐編
第12回 条件分岐(if文)
C言語のif文の書き方。条件分岐をフローチャートで視覚的に理解。
条件分岐編
第13回 比較・論理演算子
if 文の条件に書ける比較・論理演算子をまとめて学ぶ。
条件分岐編
第15回 switch文
値で分岐する switch 文の使い方を解説。
← 前の講座
第13回 比較・論理演算子
次の講座 →
第15回 switch文
この記事をシェア
X(Twitter)でシェア Facebookでシェア LINEで送る はてブ

この講座の理解を深めるおすすめ書籍

サイトで動きを理解し、書籍で演習量を補うと効果的です

📘
苦しんで覚えるC言語
MMGames 著
初心者向けの定番入門書。丁寧な解説で基礎を固められます。
Amazonで見る
📗
新・明解C言語 入門編
柴田望洋 著
図解が豊富で、演習問題も充実。大学の教科書としても採用多数。
Amazonで見る
📙
プログラミング言語C 第2版
B.W.カーニハン, D.M.リッチー 著
通称K&R。C言語の原典。基礎を終えた後のステップアップに最適。
Amazonで見る

※ 上記リンクはアフィリエイトリンクです。購入によりサイト運営を支援いただけます。