man 3 setvbuf
says:
Normally all files are block buffered.
If a stream refers to a terminal (as stdout normally does), it is line buffered.
Since puts()
uses stdout
we should expect a flush
(because of the \n
).
However, since in your example stdout
has not been used before
the redirection, I guess that the buffering behaviour is not chosen
yet.
At your first write attempt to stdout
, the underlying file descriptor
is not a terminal anymore but a regular file.
I guess the buffering behaviour is chosen at this moment.
If you add another call to puts()
in your example before the
redirection, then the buffering behaviour is chosen for the terminal
and then does not change afterwards when the redirection is performed.
In this case, your example works as you expect (without the explicit
fflush()
).
edit
Still in man 3 setvbuf
:
When the first I/O operation occurs on a file, malloc(3) is called, and a buffer is obtained.
and further:
The setvbuf() function may only be used after opening a stream and before any other operations have been performed on it.
On linux, this is consistent with your example.
In the MSDN page for setvbuf
:
stream must refer to an open file that has not undergone an I/O operation since it was opened.