程序状态的任何变化是否构成可观察的行为?

时间:2011-08-18 05:45:22

标签: c++ state language-lawyer observable-behavior

考虑以下两个程序:

计划一

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

上述两个程序是否具有相同的可观察行为?我怎么知道两个给定的程序是否具有相同的可观察行为?

1 个答案:

答案 0 :(得分:8)

  

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

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

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

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

  

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

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