はじめに
@tyu_ru_cpp さんの書かれた記事『C++でa == 1 && a == 2 && a == 3をtrueにしてみたい(クソ解法)』のブラッシュアップ版みたいなやつです。
2年近く前に流行ったネタですね。
コードの紹介
Cに見えますがC++です。
#include <stdio.h>
int test(volatile int a)
{
if (a == 1 && a == 2 && a == 3) {
puts("true");
return 0;
}
}
int main()
{
int a = 0;
test(a);
}
$ g++ -w -O2 hoge.cpp ; ./a.out
true
$
WandboxでC++コンパイラでコンパイルして実行
Cコンパイラでコンパイルして実行するとtrueとはならない
動作の解説
未定義動作の解説というのもナンセンスな話ですが一応。
@kaityo256 さんの書かれた記事『MacのGCCで返り値を返さない関数を書くと鼻から悪魔が出る』のコメントにある最適化が働いている模様です。
int の値を返す関数 test の中の条件式a == 1 && a == 2 && a == 3
が false となった場合、return 式;
がないまま関数の処理が終了してしまうことになりますが、C++ の仕様的に未定義動作となってしまうためそれはあり得んだろうということでコンパイラの最適化の働きでその分岐は削除され、結果的にa == 1 && a == 2 && a == 3
は常に true ということにしてしまうようです。
以上の動作は g++ では ver.8 以上、clang++ では ver.3.2 以上で確認できます。clang++ ver.4 以上ではこの最適化を抑止する -fno-strict-return
というコンパイルオプションも用意されており、効果も確認できます。
おわりに
おわりです。
追記
も少し C++ ぽい書き方版
#include <iostream>
bool test(volatile int a)
{
std::cout << std::boolalpha;
bool flag = a == 1 && a == 2 && a == 3;
// std::cout << flag << std::endl;
if (flag) {
std::cout << flag << std::endl;
return flag;
}
}
int main()
{
test(0);
}