Строка stdout буферизована, небуферизована или неопределена по умолчанию?
Раздел 7.9.13/7
из c99
говорится, что:
При запуске программы три текстовых потока предопределены и не требуют явного открытия - стандартный ввод (для чтения обычного ввода), стандартный вывод (для записи обычного вывода) и стандартная ошибка (для записи диагностического вывода).
При первоначальном открытии стандартный поток ошибок не полностью буферизован; стандартные входные и стандартные выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не ссылается на интерактивное устройство.
Так что это имеет смысл. Если вы помещаете стандартный вывод в файл, вы хотите, чтобы он был полностью буферизован для эффективности.
Но я не могу найти упоминания в стандарте относительно того, является ли вывод буферизованным или небуферизованным, если вы не можете определить, что устройство неинтерактивное (т. Е. Обычный вывод на терминал).
Причиной, по которой я спрашиваю, был комментарий к моему ответу, что я должен вставить fflush(stdout);
между двумя утверждениями:
printf ("Enter number> ");
// fflush (stdout); needed ?
if (fgets (buff, sizeof(buff), stdin) == NULL) { ... }
потому что я не прекращал printf
с новой строкой. Кто-нибудь может это прояснить?
1 ответ
Стандарт C99 не определяет, являются ли три стандартных потока небуферизованными или буферизованными строками: это зависит от реализации. Все известные мне UNIX-реализации имеют буферизованную строку stdin
, В Linux stdout
в строке и stderr
небуферизован.
Насколько я знаю, POSIX не накладывает дополнительных ограничений. Страница fflush POSIX отмечает в разделе ПРИМЕРЫ:
[...] Функция fflush() используется, потому что стандартный вывод обычно буферизуется, и подсказка может не сразу печататься на выходе или терминале.
Итак, замечание, которое вы добавляете fflush(stdout);
верно.
Альтернативой может быть сделать stdout
небуферизован:
setbuf(stdout, NULL);
/* or */
setvbuf(stdout, NULL, _IONBF, 0);
Но, как отмечает Р., вы можете сделать это только один раз, и это должно быть до того, как вы напишите stdout
или выполнить любое другое действие на нем. (С99 7.19.5.5 2)
Я только что прочитал недавнюю ветку на comp.lang.c
о том же самом. Одно из замечаний:
Конвенция Unix заключается в том, что
stdin
а такжеstdout
строковые буферизуются, когда связаны с терминалом, и полностью буферизуются (иначе как блочная буферизация) в противном случае.stderr
всегда небуферизован.