Difference between puts() and printf() in C while

2019-06-21 13:19发布

问题:

I was wondering the difference between puts() and printf() functions while using sleep() function.

Here is my code(In C language):

printf("hello, world");
sleep(1);
printf("Good, bye!");

After compiling and running the program, it seems that it will sleep first and then print "hello, worldGood, bye!"

However, if using puts() instead of printf(), it will print "hello, world" then sleep, and finally print "Good, bye".

puts("hello, world");
sleep(1);
puts("Good, bye!);

回答1:

This is because of buffering - by default, standard out buffers up to each new line. printf() does not include a newline, so output isn't flushed. puts() includes a newline, so output is flushed.

You can cause printf() to flush by putting a newline:

printf("hello, world\n");

or by calling fflush() directly:

fflush(stdout);

For more about buffering, see the man page for setbuf():

The three types of buffering available are unbuffered, block buffered, and
   line buffered.  When an output stream is unbuffered, information appears on
   the destination file or terminal as soon as written; when it is block 
   buffered many characters are saved up and written as a block; when it 
   is line buffered characters are saved up until a newline is output or input
   is read from any stream attached to a terminal device (typically stdin).
   ....
   If a stream refers to a terminal (as stdout normally does) it is 
   line buffered. 
   ....
   The standard error stream stderr is always unbuffered by default.


回答2:

It's because puts is also outputting a newline character which, on devices that can be determined to be interactive, causes flushing by default (for standard output) (a).

You should see a similar effect if your initial printf outputs a newline at the end:

printf("hello, world\n");

or if you fflush (stdout); before the sleep() call.

The relevant part of C11 is 7.21.3 Files, section /7:

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.

This harks back to the days of C89/90 4.9.3 Files:

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). When 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.


(a): It's not quite that simple. For starters, this is implementation dependent simply because the standard states that what constitutes an interactive device is implementation dependent (the behaviour is specified but not the thing that affects that behaviour).

Secondly (as per here), the standard only mandates when standard output becomes fully bufferd (when the device is definitely not interactive). Whether it's unbuffered or line buffered for interactive devices is an implementation decision.



回答3:

From what I understand, printf will flush the stream if a newline \n is present. puts, I'm not really sure. It may be implementation dependant.

Your sleep is just long enough for printf which is not containing a \n to flush the stream.

I recommend you flush the stream when required with fflush(stdout); Then you can avoid the sleep altogether.



标签: c sleep puts