Why does printf() not print anything before sleep()?
Asked Answered
H

4

26

I'm just learning C with Kernighan and Ritchie's book; I'm in the basics of the fourth chapter ("Functions and Program Structure"). The other day I became curious about the sleep() function, so tried to use it like this:

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

int main(void)
{
  printf(" I like cows.");
  sleep(5);
  return 0;
}

The problem is the output of the program, it looks like it does the sleep() first and then the printf(), in other words, it waits five seconds and then prints the string. So I thought, maybe the program gets to sleep() so fast that it doesn't let printf() have his work done like I want, that is print the string and then sleep.

How can I show the string and then put the program to sleep? The compiler is GCC 3.3.5 (propolice) in OpenBSD 4.3.

Helminthiasis answered 3/12, 2008 at 18:42 Comment(0)
Q
52

printf() writes to stdout (the default output stream) which is usually line buffered. The buffer isn't flushed by the time sleep is called so nothing is displayed, when the program exits all streams are automatically flushed which is why it prints right before exiting. Printing a newline will usually cause the stream to be flushed, alternatively you could use the fflush function:

int main(void)
{
  printf(" I like cows.\n");
  sleep(5);
  return 0;
}

or:

int main(void)
{
  printf(" I like cows.");
  fflush(stdout);
  sleep(5);
  return 0;
}

If you are printing to a stream that is not line buffered, as may be the case if stdout is redirected or you are writing to a file, simply printing a newline probably won't work. In such cases you should use fflush if you want the data written immediately.

Quintinquintina answered 3/12, 2008 at 18:46 Comment(5)
The reason adding a \n to the string works is that printf to the console is line buffered. However, if you redirect it to to a file it might not be enough because it uses a different buffering scheme.Granular
Interesting question then is, how can you tell which buffering mode is your current file pointer using?Sticker
@Paul, right, that is why I said it will usually cause the stream to be flushed but I'll go ahead and clarify.Quintinquintina
@Vinko, there is no standard function that will tell you what the buffering mode for a stream is but many implementations have their own functions (glibc has __flbf and __fbufsize for example).Quintinquintina
@RobertGamble, well, I had learnt that fflush (stdout) is Undefined Behavior.Borzoi
G
9

Your problem is that printf (and anything else that uses the stdio library to write to stdout (standard output)) is buffered - line buffered if it goes to the console, and size buffered if it goes to a file. If you do a fflush(stdout); after the printf, it will do what you want. You could try just adding a newline ('\n') to your string, and that would do the right thing as long as you don't redirect standard output to a file.

I'm not 100% sure, but I think stderr isn't buffered, which can cause confusion because you might see output you made to stderr before output you previously made to stdout.

Granular answered 3/12, 2008 at 18:45 Comment(4)
printf isn't buffered, the stream that it is writing to is.Quintinquintina
stderr is usually unbuffered (although it may be line buffered).Quintinquintina
why the newline('\n') does the job?Polypeptide
@johngonidelis because as I said before, it's line buffered. When it sees the end of a line, it flushes the buffer.Granular
S
6

Buffering means that all the output is stored in a place (called buffer) and is output after a certain amount of data is present in it. This is done for efficiency reasons.

Some (most?) implementations clear the buffer after a newline when writing to the console, so you can also try

printf(" I like cows.\n");

instead of the call to fflush()

Sticker answered 3/12, 2008 at 18:47 Comment(0)
C
1

I implemented time encounter as following;

for (int i = 1; i <= 60; i++) {
    printf("%02d", i);
    fflush(stdout);
    sleep(1);
    printf("\b\b");
}
Caisson answered 20/12, 2018 at 0:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.