Строка stdout буферизована, небуферизована или неопределена по умолчанию? - PullRequest
17 голосов
/ 16 сентября 2010

Раздел 7.9.13/7 из c99 гласит:

При запуске программы три текстовых потока предопределены и не требуют явного открытия - стандартный ввод (для чтения обычного ввода),стандартный вывод (для записи обычного вывода) и стандартная ошибка (для записи диагностического вывода).

При первоначальном открытии поток стандартных ошибок не полностью буферизован;стандартные входные и стандартные выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не ссылается на интерактивное устройство.

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

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

Причиной, по которой я спросил, был комментарий к моему ответу здесь , который я должен вставитьfflush(stdout); между двумя утверждениями:

printf ("Enter number> ");
// fflush (stdout); needed ?
if (fgets (buff, sizeof(buff), stdin) == NULL) { ... }

, потому что я не заканчивал printf переводом строки.Кто-нибудь может это прояснить?

1 Ответ

29 голосов
/ 19 сентября 2010

Стандарт C99 не определяет, являются ли три стандартных потока небуферизованными или буферизованными: Это зависит от реализации. Все известные мне реализации UNIX имеют буферизованную строку stdin.В Linux stdout в строке с буферизацией и stderr без буферизации.

Насколько я знаю, POSIX не накладывает дополнительных ограничений.Страница POSIX fflush в разделе ПРИМЕРЫ отмечает:

[...] Функция fflush () используется, поскольку стандартный вывод обычно буферизуется иприглашение не может быть сразу напечатано на выходе или терминале.

Таким образом, добавленное вами замечание fflush(stdout); является правильным.


Альтернативой может быть stdout небуферизованный:

setbuf(stdout, NULL);
/* or */
setvbuf(stdout, NULL, _IONBF, 0);

Но, как отмечает Р., вы можете сделать это только один раз, и это должно быть до того, как вы напишите в stdout или выполните любое другое действие на нем.(C99 7.19.5.5 2)


Я только что прочитал недавнюю ветку на comp.lang.c об одном и том же.Одно из замечаний:

Соглашение Unix заключается в том, что stdin и stdout буферизуются строкой, когда связаны с терминалом, и полностью буферизуются (иначе говоря, блочная буферизация) в противном случае.stderr всегда небуферизован.

...