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


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

9 444

9 ответов:

The 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

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

setbuf(stdout, NULL);

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

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

myprog >myfile.txt

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

во-первых, это не очень эффективно. Во-вторых, первоначальный мандат 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 без буфера.

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

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

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