7

次の 2 つのプログラムを検討してください。

プログラム 1

int main()
{
   printf( "hello\n" );
}

プログラム 2

int main()
{
   srand( 0 );
   if( rand() ) {
      printf( "hello\n" );
   } else {
      printf( "hello\n" );
   }
}

彼らは同じ観察可能な行動を持っていますか?C++ 標準 (1.9/6) によると、観察可能な動作には以下が含まれます。

  • volatileデータの読み取りと書き込み
  • ライブラリ I/O 関数

srand()rand()はおそらく I/O 関数ではありませんが (特定の実装が何らかのハードウェア ノイズ ソースを使用しているかどうかはわかりませんが)、プログラムの内部状態を変更します。彼らはデータを操作しvolatileますか? 知らない。への呼び出しprintf()は明らかに I/O 操作であり、そのシーケンスは両方のプログラムで同じです。

上記の 2 つのプログラムの動作は同じですか? 特定の 2 つのプログラムが同じ観察可能な動作をしているかどうかを知るにはどうすればよいですか?

4

1 に答える 1

8

上記の 2 つのプログラムの動作は同じですか?

あなたが言うように、それは観察可能な副作用があるかどうかsrand()に依存します. rand()すべきではありません。シーケンスは特定のシードに対して反復可能である必要があり、I/O を実行したり、揮発性データにアクセスしたりする理由が他にないため、外部ノイズ ソースは存在しません。

コンパイラがそうでないと判断できる場合 (たとえば、ヘッダーでインラインで定義されている場合、またはリンカーが追加の最適化を実行するのに十分なほどスマートである場合)、それらを省略することができます。それ以外の場合は、それらが含まれていると想定して含める必要があります。多くの実装では、これらの関数はプリコンパイルされたライブラリにあり、リンカーはそれほどスマートではないため、関数を呼び出すことになります。ただし、適切なコンパイラは、両方の分岐ifが同一であることに気付き、テストを省略する必要があります。

(更新:コメントに記載されているように、への呼び出しはrand()、コンパイラがその副作用に依存する将来の観察可能な動作がないと判断できる場合にのみ省略できます)。

特定の 2 つのプログラムが同じ観察可能な動作をしているかどうかを知るにはどうすればよいですか?

一般に、これは非常に難しい問題であり、特定できないプログラムもあります (停止問題と同様の理由で)。このような単純なプログラムの場合、監視可能な操作をリストして比較するだけです。動作が重要な方法でプログラムの入力に依存している場合、それを行うのはすぐに非常に困難になります。

于 2011-08-18T06:39:35.157 に答える