1. ホーム
  2. c++

[解決済み] オンラインIDEでプログラムの挙動がおかしい件

2023-06-17 18:01:38

質問

以下のようなC++プログラム( ソース ):

#include <iostream>
int main()
{
    for (int i = 0; i < 300; i++)
        std::cout << i << " " << i * 12345678 << std::endl;
}

これは単純なプログラムのようで、私のローカルマシンでは正しい出力、つまり次のようなものが得られます。

0 0
1 12345678
2 24691356
...
297 -628300930
298 -615955252
299 -603609574

しかし、オンライン IDE のような コーデック のようなオンライン IDE では、次のような出力が得られます。

0 0
1 12345678
2 24691356
...
4167 -95167326
4168 -82821648
4169 -7047597

なぜ for ループが 300 で終了するのはなぜですか?また、このプログラムは常に 4169 . なぜ 4169 であり、他の値ではないのでしょうか?

どのように解決するのですか?

私はオンラインコンパイラがGCCまたは互換性のあるコンパイラを使用していると仮定しています。もちろん、他のコンパイラも同じ最適化を行うことができますが、GCCのドキュメントでは、それが何を行うかをよく説明しています。

-faggressive-loop-optimizations

このオプションは、ループの反復回数の境界を導き出すために言語制約を使用するようループオプティマイザーに指示します。これは、ループコードが符号付き整数のオーバーフローやアウトオブバウンドの配列アクセスなど、未定義の動作を引き起こさないことを前提としています。ループの反復回数の境界は、ループのアンロールとピーリング、およびループ終了テストの最適化のガイドとして使用されます。このオプションはデフォルトで有効になっています。

このオプションは、単に UB が証明されたケースに基づく仮定を行うことを可能にするだけです。これらの仮定を利用するために、定数折りたたみなど、他の最適化を有効にする必要があるかもしれません。


符号付き整数のオーバーフローは未定義の動作をします。オプティマイザは、任意の値の i が 173 より大きい場合は UB が発生することを証明し、UB が発生しないと仮定できるため、オプティマイザはまた i が173より大きくなることはないと仮定できます。そして、さらに次のことを証明することができます。 i < 300 が常に真であることをさらに証明できるので、ループ条件を最適化することができます。

なぜ他の値ではなく、4169なのでしょうか?

これらのサイトはおそらく、表示する出力行数(または文字数やバイト数)を制限しており、たまたま同じ制限を共有しているのでしょう。