Каковы правила автоматической промывки буфера stdout в C?

Мне просто интересно, какие условия должны быть удовлетворены, чтобы автоматически очистить буфер stdout.

прежде всего, я был смущен тем, что этот псевдо-код не печатает вывод каждой итерации:

while (1) {
    printf("Any text");
    sleep(1);
}

но если я добавлю символ новой строки, он будет.

после нескольких экспериментов я обнаружил, что на моей машине сброшен буфер stdout:

  1. когда я ставлю в stdout 1025 символов или более;
  2. когда я читаю стандартный ввод;
  3. когда я ставлю символ новой строки в stdout;

первое условие полностью ясно - когда буфер заполнен, он должен быть сброшен. Второй тоже разумный. Но почему персонаж newline вызывает покраснение? Каковы другие имплицитные условия для этого?

5 ответов


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

когда поток unbuffered символы предназначены, чтобы появиться из источника или в месте назначения как можно скорее. В противном случае символы могут накапливаться и передаваться в среду хоста или из нее в виде блока.

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

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

поддержка этих характеристик определяется реализацией, ... C11dr §7.21.3 3


Мне просто интересно, какие условия должны быть удовлетворены, чтобы автоматически очистить буфер stdout.

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


посмотреть man-страница для setbuf(3). По умолчанию stdout установлен в режим буферизации линии.

printf() и его варианты работают с буферизованным выходом и делегируют write(). Таким образом, эта буферизация управляется реализацией библиотеки C printf, с настройками буфера и буфера, расположенными в FILE структура.

также стоит отметить разницу между разделом 3 и разделом 2 man-страниц unix. Раздел 2 состоит вызовов функций, которые напрямую разговаривают с операционной системой и делают то, что в противном случае было бы невозможно сделать из чистой пользовательской программы. Раздел 3 состоит из вызовов функций, которые пользователь может воспроизвести самостоятельно, которые часто делегируются вызовам раздела 2. Функции раздела 2 содержат низкоуровневую "магию", которая позволяет программам C взаимодействовать с внешним миром и выполнять функции ввода-вывода. функции раздела 3 могут обеспечить более удобный интерфейс для раздела 2 функции.

printf, scanf, getchar, fputs и другие FILE * функции все функции раздела 3, которые делегируют write() и read(), которые являются функциями раздела 2. read() и write() не буфер. printf() взаимодействует с буфером в FILE структура, и иногда решает отправить содержимое буфера через write().


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

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

  • реализациям не разрешается делать потоки полностью буферизованными по умолчанию, если не установлено, что они не связаны с "интерактивным устройством". Так когда? stdin / stdout-это терминалы, которые не могут быть полностью буферизованы, только линейно буферизованы (или не буферизованы).

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


существует много обстоятельств, когда буферизованный вывод в потоке сбрасывается автоматически:

  1. когда вы пытаетесь сделать вывод и выходной буфер полон.
  2. когда поток закрывается.
  3. когда программа завершает работу, вызывая exit.
  4. при записи новой строки, если поток буферизован по строке.
  5. всякий раз, когда операция ввода на любой поток читает данные из файла.

stdout is line буферизация по умолчанию.

Если вы хотите сбросить буферизованный вывод в другое время, вы можете вызвать fflush.


онлайн стандарт C2011

7.21.3 файлы
...
3 Когда поток unbuffered, символы должны появляться из источника или на назначения как можно скорее. В противном случае символы могут накапливаться и передается в среду хоста или из нее в виде блока. Когда поток полностью буферизованной, символы предназначены для передачи в среду хоста или из нее в виде блока когда буфер заполняется. когда поток линия буферизованный, символы должны быть передается в среду хоста или из нее в виде блока, когда символ новой строки встречающийся. Кроме того, символы предназначены для передачи в виде блока на хост среда при заполнении буфера, при запросе ввода в небуферизованный поток или когда входной сигнал спрошен на буферизованном линией потоке который требует передачи символы с хоста среды. Поддержка этих характеристик реализация-определена и может быть затронута через setbuf и setvbuf функции.
...
7 при запуске программы три текстовых потока предопределены и не должны быть открыты явно - стандартный ввод (для чтения обычных входных), стандартный вывод (для написания обычный выход), и Стандартная ошибка (для записи диагностического вывода). Как изначально открыл, стандартный поток ошибок не полностью буферизован;стандартный ввод и стандартный выходные потоки полностью буферизуются тогда и только тогда, когда поток можно определить, чтобы не ссылаться к интерактивному устройству.

таким образом, поток с буферизацией строки будет сброшен на новую строку. На большинстве систем у меня есть опыт работы с,stdout строка буферизуется в интерактивном сеансе.