15
7

More than 3 years have passed since last update.

C++の未定義動作でa==1&&a==2&&a==3をtrueにしてみたい

Last updated at Posted at 2019-10-08

はじめに

@tyu_ru_cpp さんの書かれた記事『C++でa == 1 && a == 2 && a == 3をtrueにしてみたい(クソ解法)』のブラッシュアップ版みたいなやつです。
2年近く前に流行ったネタですね。

コードの紹介

Cに見えますがC++です。

hoge.cpp
#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);
}

Wandboxで実行

15
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
7