fprintf和WriteConsole的输出以相反的顺序发生

时间:2014-09-10 23:51:29

标签: c++ c winapi stdio

我在Windows中看到了控制台I / O的奇怪行为。当我使用FILE *作为路径打开CONOUT$时,它应该打开控制台的stdout。如果我将该指针用于fprintf然后使用WriteConsole,您会认为这些消息将按相应的顺序排列,但它们实际上是相反的。

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <io.h>

int main(int argc, char *argv[]) {
  FILE *fout = fopen("CONOUT$", "w");
  fprintf(fout, "Hello world!\n");

  LPSTR goodbye = "Goodbye, cruel world!\n";
  DWORD length = strlen(goodbye);
  DWORD written;
  WriteConsole(_get_osfhandle(_fileno(fout)), goodbye, length, &written, NULL);

  return 0;
}

输出:

Goodbye, cruel world!
Hello world!

这是为什么?我的猜测与Win32 I / O函数和stdio同步(或者更确切地说,不是)的方式有关。我知道C ++ iostream需要特别注意与stdio同步,所以Win32可能不这样做吗?

3 个答案:

答案 0 :(得分:4)

这可能与某些缓冲stdio.h添加输出有关。尝试添加

fflush(fout);
fprintf之后

。或者你可以试试

setbuf(fout, null);

禁用输出流的缓冲。

关于“奖金”(printf正常工作):Afaik stout通常设置为在每个换行符后自动刷新。

答案 1 :(得分:2)

它几乎肯定与stdio缓冲有关,尽管理论上fout不应该是完全缓冲的。

C11§7.21.5.3/ 8:“当打开时,当且仅当可以确定不参考交互式设备时,流被完全缓冲。流的错误和文件结束指示符被清除“。因此,Windows stdio实现很可能无法确定CONOUT$是一个交互设备,但标准的措辞似乎是如果有疑问,则不应该完全缓冲打开流。它可能是行缓冲打开的,但你在\n中输出fprintf,所以在这种情况下你应该没问题,事实上,使用{{1}这或多或少证明了这一点工作。

您可以尝试使用printf关闭setvbuf上的缓冲,看看是否有帮助。

答案 2 :(得分:1)

这绝对是stdio阻碍的阻碍。我使用MSVC2012和mingw-w64实现获得了相同的输出。

我决定从stdio层切换到POSIX层,输出是:

Hello world!
Goodbye, cruel world!

您的代码略有修改:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <io.h> 
#include <fcntl.h>

int main(int argc, char *argv[]) {
  int fout = _open("CONOUT$", _O_WRONLY);
  char *hello = "Hello world!\n";
  _write(fout, hello, strlen (hello));

  LPSTR goodbye = "Goodbye, cruel world!\n";
  DWORD length = strlen(goodbye);
  DWORD written;
  WriteConsole(_get_osfhandle(fout), goodbye, length, &written, NULL);

  _close(fout);
  return 0;
}