Строка 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 всегда небуферизован.

Другие вопросы по тегам