printf on Linux vs Windows [duplicate]

2019-08-07 20:27发布

问题:

This question already has an answer here:

  • Why does printf not flush after the call unless a newline is in the format string? 9 answers

Here is some C code :

int i;
printf("This text is printed\nThis text is not until the for loop end.");
for (i = 5; i > 0; i--)
{
    printf("%d", i);
    sleep(1);
}

Why is the rest of the text after the '\n' not printed before the for loop start? Even the printf inside the for loop is only printed after the loop end. If I put a '\n' at the end of the text, it prints, but I do not want a new line.

This only happens on Linux and not on Windows (just changed sleep(1) to Sleep(1000) and added windows.h).

回答1:

It's caused by output buffering. When you call printf, the output isn't printed immediately. It is written to a buffer to be output sometime in the future. Usually a \n character causes the buffer to be flushed automatically. You can also flush the stdout buffer manually:

printf("This text is printed\nThis text is not until the for loop end.");
fflush(stdout);


回答2:

Look up setvbuf() and _IONBF vs _IOLBF vs _IOFBF. By default, when the output is to a terminal, the output is line buffered (_IOLBF). This means that output only appears when a newline is included. _IONBF is non-buffered, sometimes reserved for standard error (though that too can be line buffered). _IOFBF is fully-buffered; the output won't appear until the internal buffer is full, or you explicitly fflush() the output (or, sometimes, if you read from standard input). If you write to a pipe, or a file, the output will normally be fully buffered.

In general, you should expect to end outputs with a newline if you want to see them in a timely fashion — Windows-based examples to the contrary notwithstanding. (It is a common meme on Stack Overflow that reasonably reliably identifies when a program is written for Windows.)



回答3:

The buffer of stdout is not specified by the C standard. But POSIX implies(not requires) that usually stdout is line buffered when it's connected to a terminal, is fully buffered otherwise.

Linux follows this POSIX convention but Windows does not. You can change the default behavior using setvbuf or use fflush to flush the output, that's guaranteed by the C standard.