2010-09-16 8 views
16

Раздел 7.9.13/7 из c99 гласит:Является ли строка stdout буферной, небуферизованной или неопределенной по умолчанию?

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

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

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

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

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

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

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

ответ

26

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

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

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

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


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

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

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


Я только что прочитал recent thread на comp.lang.c примерно то же самое.Одно из замечаний:

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

+0

Вы не можете «временно» сделать 'stdout' небуферизованным. 'setbuf' и' setvbuf' имеют неопределенное поведение, если они не являются первой операцией, выполняемой в файле после ее открытия. –

+0

@R ..: Спасибо, вы правы. Я добавил это к ответу. – schot

+0

В случае буферизации строк есть ли водяной знак, если линия слишком длинная, она будет размыта? – CMCDragonkai