7

考虑以下两个程序:

节目一

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

方案二

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 操作,其顺序在两个程序中是相同的。

上面的两个程序是否具有相同的可观察行为?我如何知道两个给定程序是否具有相同的可观察行为?

4

1 回答 1

8

上面的两个程序是否具有相同的可观察行为?

正如您所说,这取决于是否srand()并且rand()具有可观察到的副作用。他们不应该;不可能有外部噪声源,因为对于给定的种子要求序列是可重复的,并且没有其他理由来执行 I/O 或访问易失性数据。

如果编译器能够确定它们没有(例如,如果它们是在头文件中内联定义的,或者链接器足够聪明,可以执行额外的优化),那么它就可以省略它们;否则,它必须假设他们这样做,并包括他们。在许多实现中,这些函数将在预编译库中,链接器不会那么聪明,因此您最终会调用这些函数;然而,一个体面的编译器应该注意到两个分支if是相同的并省略测试。

(更新:如注释中所述,rand()只有在编译器可以确定未来没有可观察的行为取决于其副作用时,也可以省略调用)。

我如何知道两个给定程序是否具有相同的可观察行为?

一般来说,这是一个非常困难的问题,并且会有一些程序无法判断(原因类似于停机问题)。对于像这样简单的程序,您可以简单地列出可观察的操作并进行比较;如果行为以不平凡的方式依赖于程序的输入,那么很快就很难做到。

于 2011-08-18T06:39:35.157 回答