if文で = と == を取り違えたときの挙動
比較のつもりで書いた if (ok = 1) が実は代入文になっているバグです。C++はこれを構文エラーとして扱わず、代入結果の値を条件として評価してしまいます。
なぜエラーが出ないのか
出力: yes(okは0のはずなのに実行される)
(エラーなし)- C++は何も報告しません。コンパイルも実行も正常に完了するためです
出力: yes(okは0のはずなのに実行される)- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 #include <iostream> 2 int main() { 3 int ok = 0; 4 if (ok = 1) { ^ 5 std::cout << "yes" << std::endl; 6 } else { 7 std::cout << "no" << std::endl; 8 } 9 return 0; 10 }
if (ok = 1)は比較ではなく代入です。okに1を代入し、その代入結果(1、真)を条件として評価するため、常にyes側が実行されます。
直し方: = を == にします。
パターン2
1 #include <iostream> 2 int main() { 3 int age = 15; 4 if (age = 18) { ^ 5 std::cout << "adult" << std::endl; 6 } else { 7 std::cout << "minor" << std::endl; 8 } 9 return 0; 10 }
if (age = 18)はageに18を代入する文で、その値(18、真)が条件として使われてしまいます。ageの実際の値である15は無視されます。
直し方: = を == にします。
パターン3
1 #include <iostream> 2 int main() { 3 int found = 0; 4 if (found = 1) { ^ 5 std::cout << "found" << std::endl; 6 } else { 7 std::cout << "not found" << std::endl; 8 } 9 return 0; 10 }
=は代入、==は比較です。1文字の書き間違いですが、C++はこれを文法的に正しいものとして受け入れてしまうためエラーにはなりません。
直し方: = を == にします。
パターン4
1 #include <iostream> 2 int main() { 3 int active = 0; 4 if (active = 1) { ^ 5 std::cout << "running" << std::endl; 6 } else { 7 std::cout << "stopped" << std::endl; 8 } 9 return 0; 10 }
if (active = 1)はactiveに1を代入し、その結果(真)を条件として使ってしまいます。
直し方: = を == にします。
パターン5
1 #include <iostream> 2 int main() { 3 int level = 3; 4 if (level = 5) { ^ 5 std::cout << "max" << std::endl; 6 } else { 7 std::cout << "not max" << std::endl; 8 } 9 return 0; 10 }
levelの実際の値(3)に関わらず、代入された5が真として扱われてしまいます。
直し方: = を == にします。
よくある誤解
エラーが出ないため「文法的に間違っていない」と勘違いされがちですが、実際には意味が変わってしまっています。if (ok = 1) はokに1を代入したうえで、その1(真)を条件として使うため常にtrueになります。
実務での勘所
C++17以降のif (auto ok = doSomething(); ok)という書き方と、if (ok = 1)を混同しないよう注意が必要です。前者はセミコロンで区切られた初期化文と条件式が別々に書かれている、意図的な新しい構文(if文の初期化子)です。後者はセミコロンが無く、代入そのものが条件として評価されてしまっているミスです。見た目は似ていても、セミコロンの有無で意味がまったく違います。