在C++中,打印空字符串是否属于可观察行为?

11

根据C++03标准的可观察行为(1.9/6),包括调用库I/O函数。现在我有以下代码:

printf( "" );

这实际上是对库I/O函数的调用,但没有任何效果。

这是可观察的行为吗?编译器是否被允许消除它?


正如代码优化一样重要。 - sharptooth
@Bo Persson:是的,如果编译器不允许这样做,我会得到额外的机器码。 - sharptooth
1
@Oli - 即使这并不重要,也不能说这不是一个有趣的问题。 - Flexo
好的,1.9/6明确表示这是可以观察到的行为,编译器无法消除它。我猜你真正想问的是为什么?因为如果编译器能够消除它,我们当然不会介意。 - hamstergene
你确定它没有任何影响吗?也许它会在内部触发一些超时,刷新一些缓冲区?或者缓冲区每N次调用就会被刷新? - PlasmaHH
5个回答

5

如果 sync_with_stdiotrue,那么这是可以观察到的。当它为真时,printf("") 强制与 std::cout 输出同步,并刷新先前缓冲的输出。


你确定 sync_with_stdio 可能会改变 stdio 的表现,而不仅仅是改变 C++ 流的工作方式,这可能会导致前者发生奇怪的事情吗? - Deduplicator

2

如果输出被重定向并且文件已关闭、被截断或以某种方式变得无效,则会观察到这一点。

  • 如果流状态已经是“坏”的话
  • 如果流状态本来就是“坏”的话

关于sync_with_...的观点也非常相关。


1

我非常怀疑,因为如果操作系统在调用printf时阻塞I/O时选择进行上下文切换,那么这种行为可能会在多线程编程中变得更加明显。

在这种情况下,如果结果取决于线程的交错方式,则肯定会产生影响。


没错,但问题是是否打印“没有效果”,因此不可“观察”。我只是提供了一个情况,它会产生实际影响。我从未声称这是标准中的内容。 - Platinum Azure
1
@Platinum:我不认为上下文切换算在内。所有代码修改都可能影响上下文切换,但是允许进行优化。 - Matthieu M.

1

理论上,你可以编写一个 C 库来根据时间刷新缓冲区。在这种情况下,打印空字符串可以导致刷新,从而产生可见效果。


-3

当然,这会有可观察的行为 - 它必须生成一个调用write()系统调用的底层文件描述符。进行系统调用是非常可观察的行为。

考虑一个极端的例子,内核中的文件描述符可能由设备驱动程序提供服务,每次调用写文件操作时都会发出警报声(好吧,有点人为的例子,我承认 :-) ...


3
我本来以为缓冲的库会因为没有字节被添加到缓冲中而执行无操作。唯一可观察到的迹象是CPU使用率更高。 - Ed Heal
1
如果将 CPU 使用率视为可观察行为,则所有优化都无效! - @Ed Heal - Flexo
1
如果我的电脑每次修改 RAM 时都发出警报声怎么办?递增一个整数是否算作可观察行为? - Benjamin Lindley
3
@Benjamin Lindley:哈哈,我猜你也不在乎——反正你的生活已经很悲惨了。 - sharptooth
1
-1,错误。没有理由假设 write 调用存在。如果操作系统只有一个 PUTCHAR(C) 调用,那么 printf 实现将不得不循环。显然,对于 "" 的循环将完全不调用 PUTCHAR,也就是说不可观察到。 - MSalters
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接