Почему printf() не печатает ничего перед сном()?

Я просто изучаю C с книгой Kernighan и Ritchie; Я вхожу в основы четвертой главы (функции). На днях мне стало интересно узнать о функции sleep(), поэтому попытался использовать ее так:

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

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

Проблема заключается в выходе программы, она выглядит как сначала sleep(), а затем printf(), другими словами, она ждет пять секунд и затем печатает строку. Поэтому я подумал, может быть, программа добирается до sleep() настолько быстро, что не позволяет printf() выполнять свою работу так, как я хочу, то есть печатать строку, а затем спать.

Как я могу показать строку, а затем перевести программу в режим сна? Компилятор GCC 3.3.5 (прополис) в OpenBSD 4.3.

PS Я не знаю, как правильно поставить строки препроцессора.

Ответы

Ответ 1

printf() записывается в stdout (выходной поток по умолчанию), который обычно буферизируется по строке. Буфер не сбрасывается ко времени sleep, так что ничего не отображается, когда программа выходит из всех потоков, автоматически очищается, и поэтому она печатается прямо перед выходом. Печать новой строки обычно приводит к покраске потока, альтернативно вы можете использовать функцию fflush:

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

или

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

Если вы печатаете в потоке, который не является буфером строки, как это может быть в случае, если stdout перенаправляется или вы пишете файл, просто печать новой строки, вероятно, не будет работать. В таких случаях вы должны использовать fflush, если вы хотите, чтобы данные были записаны немедленно.

Ответ 2

Ваша проблема в том, что printf (и все, что использует библиотеку stdio для записи в stdout (стандартный вывод)) буферизуется - буферизируется в строке, если она идет на консоль, и размер буферизуется, если он идет в файл. Если вы выполните fflush(stdout); после printf, он сделает то, что вы хотите. Вы можете попробовать просто добавить новую строку ('\n') в свою строку, и это будет сделано правильно, если вы не перенаправляете стандартный вывод в файл.

Я не уверен на 100%, но я думаю, что stderr не буферизирован, что может вызвать путаницу, потому что вы можете увидеть вывод, который вы сделали для stderr, перед выводом, ранее сделанным в stdout.

Ответ 3

Буферизация означает, что весь вывод хранится в месте (называемом буфером) и выводится после того, как в нем присутствует определенное количество данных. Это делается по соображениям эффективности.

Некоторые (большинство?) реализаций очищают буфер после новой строки при записи на консоль, поэтому вы также можете попробовать

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

вместо вызова функции fflush()

Ответ 4

Я реализовал время встречи следующим образом;

for (int i = 1; i <= 60; i++) {
    printf("%02d", i);
    fflush(stdout);
    sleep(1);
    printf("\b\b");
}