printf
書式文字列に改行が含まれていない限り、呼び出し後にフラッシュしないのはなぜですか? これは POSIX の動作ですか? printf
毎回すぐにフラッシュするにはどうすればよいですか?
10 に答える
ストリームは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);
いいえ、これは 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
関数によって影響を受ける可能性があります。
これはおそらく効率のためであり、複数のプログラムが単一の 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)
(NULL
すべてをフラッシュすることを意味します) をフラッシュします。
注: Microsoft ランタイム ライブラリは行バッファリングをサポートしていないため、次のようになりprintf("will print immediately to terminal")
ます。
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setvbuf
stdout はバッファリングされるため、改行が出力された後にのみ出力されます。
すぐに出力するには、次のいずれかを行います。
- stderr に出力します。
- stdout をバッファリングしないようにします。
デフォルトでは、stdout は行バッファリングされ、stderr はバッファリングされず、ファイルは完全にバッファリングされます。
代わりに、バッファリングされていない stderr に fprintf できます。または、必要に応じて stdout をフラッシュできます。または、stdout を unbuffered に設定できます。
setbuf(stdout, NULL);
バッファリングを無効にするために使用します。