Почему printf не сбрасывается после вызова, если новая строка не находится в строке формата?

почему printf Не смывать после вызова, если новая строка не находится в строке формата? Это поведение POSIX? Как я мог! .. --0--> немедленно смывать каждый раз?

9 ответов


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

печать в stderr вместо использования fprintf:

fprintf(stderr, "I will be printed immediately");

Flush stdout всякий раз, когда вам нужно использовать fflush:

printf("Buffered, will be flushed");
fflush(stdout); // Will now print everything in the stdout buffer

редактировать: из комментария Энди Росса ниже вы также можете отключить буферизацию на stdout, используя setbuf:

setbuf(stdout, NULL);

нет, это не поведение POSIX, это поведение ISO (ну, это is поведение POSIX, но только в той мере, в какой они соответствуют ISO).

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

myprog >myfile.txt

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

во-первых, это не очень эффективно. Во-вторых, первоначальный мандат ANSI C должен был в первую очередь кодифицировать существующей поведение, а не выдумывать новая поведение, и эти проектные решения были приняты задолго до того, как ANSI начал процесс. Даже ISO в настоящее время действует очень осторожно при изменении существующих правил в стандартах.

Что касается того, как справиться с этим, если вы fflush (stdout) после каждого выходного вызова, который вы хотите увидеть немедленно, это решит проблему.

кроме того, вы можете использовать setvbuf перед началом работы на stdout, чтобы установить его в unbuffered, и вам не придется беспокоиться о добавлении все эти fflush строки вашего кода:

setvbuf (stdout, NULL, _IONBF, BUFSIZ);

просто имейте в виду, что может повлиять на производительность совсем немного, если вы are отправка вывода в файл. Также имейте в виду, что поддержка этого определяется реализацией, а не гарантируется стандартом.

ISO C99 раздел 7.19.3/3 соответствующий бит:

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

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

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

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

поддержка этих характеристик определяется реализацией и может быть затронута через setbuf и setvbuf функции.


это, вероятно, так из-за эффективности и потому, что если у вас есть несколько программ, пишущих в один TTY, таким образом, вы не получаете символы на линии переплетены. Поэтому, если программа A и B выводятся, вы обычно получаете:

program A output
program B output
program B output
program A output
program B output

это воняет, но это лучше, чем

proprogrgraam m AB  ououtputputt
prproogrgram amB A  ououtputtput
program B output

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


чтобы немедленно смыть вызов fflush(stdout) или fflush(NULL) (


Примечание: библиотеки Microsoft runtime не поддерживают буферизацию строк, поэтому printf("will print immediatelly to terminal"):

http://msdn.microsoft.com/en-us/library/86cebhfs.aspx


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

чтобы получить немедленный выход, либо:

  1. печать в stderr.
  2. сделайте stdout unbuffered.

по умолчанию stdout буферизован по строке, stderr не буферизован и файл полностью буферизован.


вы можете fprintf для stderr, который не является буферизованным, вместо этого. Или вы можете смыть stdout, когда захотите. Или вы можете установить stdout в unbuffered.


использовать setbuf(stdout, NULL); для отключения буферизации.