1

I have read many questions with people asking why printf did not work before a while loop; the answer was that it was not flushing stdout because they did not have a new line character in their format string. However, the following simple code is still not producing output for me:

#include <stdio.h>

int main() {

    printf("Hello world!\n");
    while (1);

    return 0;

}

However, adding fflush(stdout); after the printf call produces output. The new line character is supposed to make this unnecessary, so why does it not work without it?

TheGreenFrog
  • 155
  • 4
  • 1
    I do not reproduce. What's your system? How to you invoke your program? – AProgrammer Dec 14 '19 at 19:40
  • @user3121023 @AProgrammer I'm using mingw with Eclipse on Windows. Output is produced perfectly fine without `fflush(stdout);` if I omit the while loop, though. – TheGreenFrog Dec 14 '19 at 19:45
  • 1
    Why do you think the newline makes it unnecessary? There are many factors. In some common cases, ending the string with a newline will cause the standard library functions to flush the stream. As you discovered, not always. So don't rely on implicit behavior. If you want the stream to be flushed, flush it. – William Pursell Dec 14 '19 at 19:53
  • Your run-time isn't considering the output to eclipse as an interactive device and thus does full buffering. I don't know enough about Windows and Eclipse to comment further, but IMO this is a bug somewhere else than your code. – AProgrammer Dec 14 '19 at 20:16
  • 1
    "The new line character is supposed to make this unnecessary," --> Incorrect conclusion. Depends on buffering mode. See [What are the rules of automatic stdout buffer flushing in C?](https://stackoverflow.com/q/39536212/2410359). – chux - Reinstate Monica Dec 15 '19 at 00:23

2 Answers2

3

It's quite common for stdout to be line-buffered when connected to a terminal (flushed on line feed), and block-buffered otherwise (flushed when buffer is full).

For example,

#include <stdio.h>
#include <unistd.h>

int main(void) {
   printf("foo\n");
   sleep(5);
   return 0;
}

Test:

$ ./a
foo
[5s pause]

$ ./a | cat
[5s pause]
foo

(gcc on Linux)


I'm using mingw with Eclipse on Windows.

It seems that Eclipse is connecting the stdout of your program to a pipe so it can collect the output and display it in its window. Your program thus uses block buffering for stdout.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • "Eclipse is connecting the stdout of your program to a pipe" I'd have expected the use of the equivalent of a pseudo-terminal. Is there a reason for which Eclipse isn't doing that? – AProgrammer Dec 14 '19 at 20:13
  • @AProgrammer, Just to be clear, I'm not speaking from experience; I'm just going based on the OP's observations. That said, I don't know, but it wouldn't surprise me if Windows didn't have an equivalent to pttys. In fact, I'd actually be surprised if it did have an equivalent to pttys. But I'm not exactly knowledgeable about such things. It could also be to avoid portability issues, especially since Eclipse is written in Java. – ikegami Dec 14 '19 at 20:18
2

A very good answer by @schot here. He said :

The C99 standard does not specify if the three standard streams are unbuffered or line buffered: It is up to the implementation. All UNIX implementations I know have a line buffered stdin. On Linux, stdout is line buffered and stderr unbuffered.

One way to be sure that your line(s) will be printed directly is making stdout unbuffered:

setbuf(stdout, NULL);
/* or */
setvbuf(stdout, NULL, _IONBF, 0);

But you can only do this once, and it must be before you write to stdout or perform any other operantion on it. (C99 7.19.5.5 2)

Additional Info :

Shouldn't a new line character flush the output?

-It depends, if the output device is determined to be interactive (e.g. a terminal) the newline flush the buffer. Otherwise new line(s) don't flush the buffer.

What constitutes an interactive device is implementation-defined (C99 section 5.1.2.3/6) 

Ben Souchet
  • 1,450
  • 6
  • 20
  • But regardless of whether stdout is unbuffered or line buffered, shouldn't a new line character flush the output either way? – TheGreenFrog Dec 14 '19 at 19:49
  • 1
    @TheGreenFrog As the quote in the answer says "it is up to the implementation". That is, there is no requirement to flush after a newline and clearly the mingw implementation doesn't. – kaylum Dec 14 '19 at 19:53
  • @TheGreenFrog It depends, if the output device is determined to be interactive (like a terminal) then the newline flush the buffer. (What constitutes an interactive device is implementation-defined). Otherwise the new line doesn't flush the buffer( we say that stdout is 'fully buffered') – Ben Souchet Dec 14 '19 at 19:58