4

I have just learned about stream buffering in C. As I understand, printf() in C is buffered and it only prints when it hits a new line, the buffer is full or when we flush stdout manually. Then I try these lines of code:

#include <stdio.h>

int main() {
    printf("Hello world");
    while(1);
}

Theoretically, the console will be received nothing, since Hello world is still in the buffer. But for some reasons, my console still show this string. Why is it like that?

EDIT: I am using the command prompt in Windows 10.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Does this answer your question? [What is it with printf() sending output to buffer?](https://stackoverflow.com/questions/45385807/what-is-it-with-printf-sending-output-to-buffer) – Ryan Zhang Jun 13 '22 at 05:06
  • I tested your program in Debian Linux and I saw no output at all. In MSYS2 (Windows) with MinTTY I only saw output after I terminated the program with Ctrl+C. Where are you testing this program? Sometimes the flushing behavior depends on whether the standard output is connected to a terminal or a file. – David Grayson Jun 13 '22 at 05:10
  • @RyanZhang The provided link answers "why the buffers are flushed when the application exits": "When an input is about to happen on the same device, the buffer must be flushed" or "The buffers are also flushed when the associated files are closed". But it seems that in OPs example, a newline is printed before application exit without an input. – David Ranieri Jun 13 '22 at 05:22
  • *"As I know, printf() in C is buffered"*. I've never had to manually flush `printf()` in my life, nor have I ever seen documentation saying this is required. If you provide links to your sources, you might get answers that directly address your question. I mean, just because it is buffered, does not mean that it requires manual control. I'd be interested to know where you got these rules from. – Nagev Jun 13 '22 at 05:43
  • @Nagev I just try to understand what a buffer looks like, so I set an example to check whether it is right. You are true that it is not because of being buffered so it have to be flushed manually. However in this case, no condition is met for it to be flushed automatically( new line character, full - buffered, or a fflush(stdout) command ), the infinite while loop has blocked that. It is still printed to the console, and confusing for me. – Nguyễn Tùng Dương Jun 13 '22 at 06:07
  • I fully understand the question and the code. What I am asking is the source of your knowledge, assumption or expectation that it needs "new line character, full - buffered, or a fflush(stdout) command". I am not saying it is not true, it's just that I have not seen it in any book I've read (e.g. The C Programming Language) or documentation (e.g. `man 3 printf`). So if you provide the relevant quotes and/or links we might be able to get more context. As it stands, I'd be inclined to answer that `printf()` does *not* require a newline etc. to show the output in the terminal/stdout. – Nagev Jun 13 '22 at 06:26
  • Well, this is interesting, I just verified that indeed on Linux it won't print on the terminal while it stays in the loop. With a new line it will print immediately, as you expected. I'd still like to see an official reference to this behavior. The Windows exception is correctly explained in the current answer. – Nagev Jun 13 '22 at 06:47
  • It is not a Windows/*nix thing. With gcc in eclipse under Windows, nothing appears. The result depends on more than just the OS. – chux - Reinstate Monica Jun 13 '22 at 06:54
  • @Nagev There are many sources on Google saying about this. I don't have any documentation – Nguyễn Tùng Dương Jun 13 '22 at 08:26
  • @Nagev You can search for such keywords like "line buffering, full buffering" on google, that's what I know – Nguyễn Tùng Dương Jun 13 '22 at 08:38
  • 2
    Correct, I should have said "with gcc" rather than "on Linux", it was like using a brand name instead instead of the product, just habit (gcc is common on Linux and Microsoft compilers on Windows). @NguyễnTùngDương there's lots of conflicting or incomplete information on the Internet, that's why I wanted to know what the official standard says about this, and since you asked the question, it would be nice to have it added. Seems like chux's answer says that it's implementation dependent, which is what I suspected. – Nagev Jun 13 '22 at 08:45

2 Answers2

5

printf() in C is buffered and it only prints when it hits a new line

Not quite.

Streams are commonly 1 of 3 modes: unbuffered, fully buffered, line buffered. Often stdout is line buffered, flushing data when printing a '\n', its internal buffer is full or due to explicit commands like fflush(stdout).

Yet C specifies about these 3 modes: Support for these characteristics is implementation-defined. C17dr § 7.21.3 3.

Thus both seeing output and not seeing output are compliant for OP's code.

To ensure output is seen, flush. Otherwise, live with implementation defined behavior.

printf("Hello world");
fflush(stdout); // add
while(1);
chqrlie
  • 131,814
  • 10
  • 121
  • 189
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
4

I'm not sure what part of the C standard you were reading, but the behavior you are seeing in Windows is correct according to Microsoft's documentation of their C runtime library:

Files opened using the stream routines are buffered by default. The stdout and stderr functions are flushed whenever they are full or, if you are writing to a character device, after each library call.

That documentation also links to a Microsoft-specific setvbuf function you can use to control the buffering if you want. I generally just let the runtime library use its default settings and then I call fflush(stdout) explicitly at every place where I want to ensure the output is flushed.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • What does "writing to a character device" mean here. It's a little confusing for me – Nguyễn Tùng Dương Jun 13 '22 at 05:32
  • @DavidGrayson nice quote, but `while(1);` does not look like a "library call", does it mean that there is an implicit `fflush` on every call to `printf`? – David Ranieri Jun 13 '22 at 05:40
  • 3
    @DavidRanieri — yes, and it explains why people working on Windows don't think a newline at the end of the output is necessary. – Jonathan Leffler Jun 13 '22 at 05:44
  • 1
    @JonathanLeffler is there any document referencing to it or it's just your experience – Nguyễn Tùng Dương Jun 13 '22 at 05:53
  • 3
    The link in this answer is the document referencing it. What Microsoft is saying is every call to `printf()` (the library call) which is essentially writing to a "character device", i.e. the console (stdout), will be immediately flushed, i.e. shown on the terminal. So what you're seeing matches the documentation. – Nagev Jun 13 '22 at 06:52