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

sha*_*oth 7 c++ state language-lawyer observable-behavior

考虑以下两个程序:

程序之一

int main()
{
   printf( "hello\n" );
}
Run Code Online (Sandbox Code Playgroud)

计划二

int main()
{
   srand( 0 );
   if( rand() ) {
      printf( "hello\n" );
   } else {
      printf( "hello\n" );
   }
}
Run Code Online (Sandbox Code Playgroud)

他们是否有相同的可观察行为?根据C++标准(1.9/6),可观察的行为包括:

  • 读取和写入volatile数据
  • 库I/O函数

现在,srand()rand()有可能不是I/O功能(虽然我不知道一个给定的实现是否会使用一些硬件噪声源),但他们修改程序的内部状态.他们操纵volatile数据吗?我不知道.调用printf()显然I/O操作及其序列在两个程序中都是相同的.

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

Mik*_*our 8

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

至于你说的,那要看是否srand()rand()具有可观察到的副作用.他们不应该; 不存在外部噪声源,因为对于给定的种子,序列需要是可重复的,并且没有其他原因来执行I/O或访问易失性数据.

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

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

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

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