627

printf書式文字列に改行が含まれていない限り、呼び出し後にフラッシュしないのはなぜですか? これは POSIX の動作ですか? printf毎回すぐにフラッシュするにはどうすればよいですか?

4

10 に答える 10

821

ストリームはstdoutデフォルトで行バッファリングされるため、改行に達した後 (または指示されたとき) にのみバッファ内にあるものを表示します。すぐに印刷するためのオプションがいくつかあります。

  • stderr代わりにfprintf(stderrデフォルトでバッファリングされていません) を使用して出力します:

    fprintf(stderr, "I will be printed immediately");
    
  • stdout必要なときにいつでもフラッシュしてくださいfflush:

    printf("Buffered, will be flushed");
    fflush(stdout); // Will now print everything in the stdout buffer
    
  • 以下を使用して、stdout でのバッファリングを無効にしsetbufます。

    setbuf(stdout, NULL);
    
  • または、より柔軟なsetvbuf:

    setvbuf(stdout, NULL, _IONBF, 0); 
    
于 2009-11-11T17:04:46.113 に答える
138

いいえ、これは POSIX の動作ではなく、ISO の動作です (まあ、これPOSIX の動作ですが、ISO に準拠している場合に限られます)。

標準出力は、対話型デバイスを参照していることが検出された場合は行バッファリングされ、それ以外の場合は完全にバッファリングされます。したがってprintf、送信する改行を取得しても、フラッシュしない状況があります。たとえば、次のとおりです。

myprog >myfile.txt

ユーザーと対話している場合、ユーザーはおそらくすべての行を見たいので、これは効率的に理にかなっています。出力をファイルに送信している場合、相手側にユーザ​​ーがいない可能性が最も高いです (不可能ではありませんが、ファイルを追跡している可能性があります)。ここで、ユーザーはすべての文字を見たいと主張することができますが、それには 2 つの問題があります。

1つ目は、あまり効率的ではないということです。2 つ目は、元の ANSI C の義務は、新しい動作を発明するのではなく、主に既存の動作を成文化することであり、これらの設計上の決定は ANSI がプロセスを開始するずっと前に行われたことです。現在、ISO でさえ、標準の既存のルールを変更する際には非常に慎重に取り組んでいます。

それに対処する方法についてはfflush (stdout)、すぐに表示したいすべての出力呼び出しの後にすれば、問題は解決します。

または、 をsetvbuf操作する前にを使用して、バッファなしに設定すると、これらすべての行をコードにstdout追加することを心配する必要がなくなります。fflush

setvbuf (stdout, NULL, _IONBF, BUFSIZ);

出力をファイルに送信する場合、パフォーマンスにかなり影響する可能性があることに注意してください。また、これのサポートは実装定義であり、標準では保証されていないことに注意してください。

ISO C99 セクション7.19.3/3は関連するビットです。

ストリームがunbufferedの場合、文字はソースまたは宛先からできるだけ早く表示されるように意図されています。そうしないと、文字が蓄積され、ブロックとしてホスト環境との間で送受信される可能性があります。

ストリームが完全にバッファリングされている場合、文字は、バッファがいっぱいになったときにブロックとしてホスト環境との間で送受信されることを意図しています。

ストリームがline bufferedの場合、文字は、改行文字が検出されたときにブロックとしてホスト環境との間で送受信されることを意図しています。

さらに、文字は、バッファがいっぱいになったとき、バッファされていないストリームで入力が要求されたとき、またはホスト環境からの文字の送信を必要とするラインバッファ付きストリームで入力が要求されたときに、ブロックとしてホスト環境に送信されることを意図しています。 .

これらの特性のサポートは実装定義であり、関数setbufおよびsetvbuf関数によって影響を受ける可能性があります。

于 2010-11-17T03:52:28.560 に答える
31

これはおそらく効率のためであり、複数のプログラムが単一の 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

改行でフラッシュすることさえ保証されていないため、フラッシュが重要な場合は明示的にフラッシュする必要があることに注意してください。

于 2009-11-11T17:54:06.413 に答える
30

すぐに呼び出しfflush(stdout)またはfflush(NULL)(NULLすべてをフラッシュすることを意味します) をフラッシュします。

于 2009-11-11T16:26:05.647 に答える
15

注: Microsoft ランタイム ライブラリは行バッファリングをサポートしていないため、次のようになりprintf("will print immediately to terminal")ます。

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setvbuf

于 2010-10-26T20:47:31.793 に答える
13

stdout はバッファリングされるため、改行が出力された後にのみ出力されます。

すぐに出力するには、次のいずれかを行います。

  1. stderr に出力します。
  2. stdout をバッファリングしないようにします。
于 2009-11-11T16:25:08.717 に答える
11

デフォルトでは、stdout は行バッファリングされ、stderr はバッファリングされず、ファイルは完全にバッファリングされます。

于 2010-07-29T02:02:19.177 に答える
10

代わりに、バッファリングされていない stderr に fprintf できます。または、必要に応じて stdout をフラッシュできます。または、stdout を unbuffered に設定できます。

于 2009-11-11T16:26:49.730 に答える
10

setbuf(stdout, NULL);バッファリングを無効にするために使用します。

于 2015-05-31T03:22:52.183 に答える