【问题标题】:Why is the output order different from the call order when using fprintf with stdout or stderr?为什么将 fprintf 与 stdout 或 stderr 一起使用时,输出顺序与调用顺序不同?
【发布时间】:2022-01-15 03:46:48
【问题描述】:

我的环境是 Debian GNU/Linux 11。

带有参数stdoutstderrfprintf 函数给出了意外的输出顺序。

int main() {
    std::cout << "Hello, World!" << std::endl;
    fprintf(stderr, "22222\n");
    fprintf(stdout, "111\n");
    printf("3333 \n");
    printf("44444 \n");
    return 0;
}

我已经运行了很多次,得到了很多不同的结果:

//①
22222
Hello, World!
111
3333 
44444

//②
Hello, World!
111
3333 
44444 
22222

这是什么原因? 或者,我想了解现象,需要什么知识?

据我了解,输出日志应该是这样的:

//③
Hello, World!
22222
111
3333 
44444 

关于①/②的两个输出日志,没看懂。

我认为日志③是对的,但它没有出现,这让我感到奇怪。

【问题讨论】:

  • the code only output like ② , but appear ① 是什么意思?并且没有 C/C++ 语言。 std::cout 在 C 中不存在
  • 整洁,但很好的例子说明了为什么你不应该越过溪流。即使在与 Gozer 战斗时。
  • 您注意到“22222”是唯一不正常的东西,对吧?那是因为您将其打印到 不同 输出流而不是其他所有输出流,并且不要求两者以与输出相同的顺序打印。还要注意其他一切都井井有条吗?这是因为std::cout 默认“绑定”到 C 标准输出流。如果您断开该连接,您可能会获得更多随机排序。原因可能与流何时刷新有关。
  • 如果你想要一个特定的顺序,请确保在重要点刷新流。更好的是,不要混合输出方法。

标签: c++ printf stdout stderr


【解决方案1】:

输出从不像②,因为output to stderr isn't buffered 所以22222 将被立即刷新,并且会在任何其他数字之前。输出到stdout 可以是line-buffered(Linux 上的默认值)或全缓冲(Windows 上的默认值)

输出也不应该像①那样,因为you're already flushing with std::endl in the first line,因此Hello, World!将首先打印。这就是为什么永远不要使用std::endl,除非你真的知道它在做什么。始终使用std::cout &lt;&lt; "Hello, World!\n";。见"std::endl" vs "\n"

Hello, World!
22222
111
3333 
44444

如果有任何差异,则说明您的标准库存在一些问题

默认情况下the legacy and C++ streams are also synchronized,因此可以混合使用两种类型的流,但会带来一些性能损失。你可以像这样禁用它

std::ios::sync_with_stdio(false);

为了获得更好的性能,但现在Hello, World! 字符串可以在任何地方打印

【讨论】:

  • @Tom 什么是克莱恩?而且你不用运行 g++ 来得到那个输出,你只是用它来编译程序然后运行程序
  • 1.我使用 g++ 编译 main.cpp ,得到 a.out 文件,然后运行 ​​a.out got log ③。 2. CLion 是 IDE,我使用 CLion 运行多次得到输出①和② 3. 抱歉我打错了。
  • "为了获得更好的性能......" 在一个产生数十、数百或数千个输出的程序中......很好,但与使用 I 非常相关/O 在单个程序中。这里没有任何区别。
猜你喜欢
  • 2014-03-11
  • 1970-01-01
  • 2011-10-30
  • 2018-03-29
  • 1970-01-01
  • 2018-10-31
  • 2021-01-31
  • 1970-01-01
  • 2019-03-24
相关资源
最近更新 更多