Originally Posted by
c99
When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible.
Otherwise characters may be accumulated and transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled.
When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered.
Furthermore, characters are intended to be transmitted as a block to the host environment
- when a buffer is filled,
- when input is requested on an unbuffered stream,
- or when input is requested on a line buffered stream that requires the transmission of characters from the host environment.
Support for these characteristics is implementation-defined, and may be affected via the setbuf and setvbuf functions.
First two sentences, anything other than unbuffered may delay the output of data from the program to the environment.
Third sentence, see below; it typically applies when stdio from a program is redirected.
Fourth sentence, this refers to what most people regard as vanilla line buffered streams.
The fifth sentence onwards ("Furthermore...") has this large "implementation-defined" proviso attached to it.
So handy features like "stdout is automatically flushed when buffered stdin is requested" (the third bullet) simply may not apply.
Even where you have the feature, a call to setvbuf might cause it to be lost again.
Originally Posted by
c99
At program startup, three text streams are predefined and need not be opened explicitly
— standard input (for reading conventional input), standard output (for writing
conventional output), and standard error (for writing diagnostic output).
As initially opened, the standard error stream is not fully buffered;
the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
The meaning of the last sentence being, that if it is an interactive device, then you don't know what kind of stream you have.
Most systems seem to go with line buffered (for both), but that doesn't help your argument.
Remember, your "interactive" program could easily end up being controlled as a child process at the end of a pipe (and not a terminal).
In such a case, the program would probably determine that input was NOT interactive, and drop into straight forward fully buffered mode.
Here's an experiment on my Ubuntu Linux.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("fail");
if ( argc > 1 && argv[1][0] == 'n' ) printf("\n");
if ( argc > 1 && argv[1][0] == 'f' ) fflush(stdout);
int c = getchar();
char ch = (char)c;
write(1,&ch,1);
return 0;
}
And the results:
Code:
$ ./a.out
failq
q$
$ ./a.out n
fail
q
q$
$ ./a.out f
failq
q$
$ ./a.out < foo.c
#fail$
$ ./a.out n < foo.c
fail
#$
$ ./a.out f < foo.c
fail#$
In interactive mode, all is as you argue to be true. The string does indeed appear without any further hints to flush stdout.
The echo of the input always happens after the string.
If input is redirected however, things are different.
Without a hint to flush the output stream, the input is echoed BEFORE the supposed output.
Any correct program should produce the same output regardless of the exact nature of the input it is receiving.
Now imagine this was at the end of a pipe, and the controlling program was expecting to "see" your prompt (without a \n or a fflush) before sending more data. It's broken Jim.