これに対する答えは、fflush(stream)
は出力ストリームに対してのみ正式に定義されているので、fflush(stdout)
はOKですが、fflush(stdin)
はNGです。
の目的は、OSに任意のバッファを基礎ファイルへフラッシュさせることにあります。 正当な使用例として、学生はしばしば次のようなことをすると「プロンプトが表示されない!」という問題が発生します:
printf("Enter a number: ");
しかし、これがうまくいくことがわかります:
printf("Enter a number:\n");
もちろん、彼らはプロンプトの後に改行をしたくないので少し問題が発生しました。
その理由は、stdout
への出力は OS によってバッファリングされており、デフォルトの動作は、改行があったときに実際に端末に出力を書き込むだけだからです (多くの場合、改行はありません)。 printf()
の後に fflush(stdout)
を追加すれば問題は解決します:
printf("Enter a number: ");fflush(stdout);
さて、類推してみると、fflush(stdin)
は使われていない入力をすべて破棄すべきだと考える人がよくいますが、少し考えてみるとそれはあまり意味のあることではないですね。 入力バッファを「フラッシュ」するとはどういう意味でしょうか。 どこに「流す」のでしょうか? 出力バッファをフラッシュすると、出力はその下のファイルかターミナルに送られ、いずれはそこに行き着くことになりますが、入力は「いずれは」どこに行き着くのでしょうか? 知る由もありません! 入力ストリームのデータがファイルやパイプやソケットから来る場合、どのような挙動になるのでしょうか? 入力ストリームではfflush()
の挙動がどうなるかは全く不明ですが、出力ストリームではどんな場合でも非常に明確です。 したがって、fflush()
は出力ストリームに対してのみ定義されています。
fflush(stdin)
の誤った使用が一般的になった理由は、何年も前に、いくつかのオペレーティングシステムが、多くの人の期待通りに動作し、未使用の入力を破棄する方式を実装していたためです。 マイクロソフトのDOSが良い例です。
「余分な」不要なターミナル入力に対して行うべき正しいことは、単にそれを読んで何もしないことです。 これは fflush(stdin)
を呼び出すのと同じくらい簡単で、どこでも動作し、形式的に未定義の動作に依存しない。
C 標準では以下のように述べられている:
stream が出力ストリームまたは最新の操作が入力でない更新ストリームを指す場合、fflush 関数はそのストリームに対してホスト環境に配信されるべき任意の未書き込みデータをファイルに書き込ませるが、その他の場合の動作は未定義である。
POSIX では (C 標準に明示的に従った):
stream が出力ストリームまたは更新ストリームを指していて、直近の操作が入力でない場合、 fflush() によってそのストリームに対する未書き込みのデータはファイルに書き込まれなければならない、 …
しかし、Linux の man ページには次のように書かれている:
出力ストリームに対しては、fflush() は与えられた出力または更新ストリームに対するすべてのユーザ空間バッファリングデータをストリームの基本書き込み関数で強制的に書き込む。 入力ストリームでは、fflush() は、基礎となるファイルから取得されたが、アプリケーションによって消費されていない任意のバッファリングされたデータを破棄します。 ストリームのオープン状態は影響を受けません。