我在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可能不这样做吗?
答案 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;
}