1

次のプログラムは有効な C プログラムですか?

#include <stdio.h>

int main()
{
    fwrite("x", 1, 1, stderr);
    fflush(stderr);
    fgetc(stderr);
    fwrite("y", 1, 1, stderr);
    return 0;
}

stderr から読み取ろうとしていることに注意してください。

Visual C++ 2008 でコンパイルして実行すると、次の出力が得られます。

xy

これは理にかなっています。ただし、stderr をファイル ( test.exe 2> foo.txt) にリダイレクトすると、「デバッグ アサーションに失敗しました」というメッセージが表示され、「ストリーム カウントに一貫性がありません。連続した読み取りと書き込みの間でフラッシュします」というメッセージが表示されます。読み取りと書き込みの間に a を追加するfflushと、問題が解決します。(これはデバッグ ビルドで発生します。リリース ビルドでは、2 番目の書き込みはサイレントに失敗します)。

この動作は正しいですか、それともコンパイラライブラリのバグですか? Cで読み取りまたは書き込みがいつ違法であるかを説明するルールはどこにも見つかりませんでした。

4

1 に答える 1

3

C99 は、7.19.5.3 ( fopen) のパラグラフ 6 で次のように述べています。

ファイルが更新モード ('+'上記の引数値のリストの 2 番目または 3 番目の文字mode) で開かれると、関連するストリームで入力と出力の両方が実行される場合があります。ただし、fflush入力操作が end-of に遭遇しない限り、出力の直後に関数呼び出しを介さずに入力が続くことはありません [...]。 -ファイル。

このコーナーケースを実際に発見したことをお祝いします。上記で引用したものに違反しているため、ライブラリの実装は完全に正しいです。

ちなみに、から読むことも珍しくありませんstderr。これは、stdinstdoutがリダイレクトされ、使用できる端末がない場合に便利です。C99 は読み取り可能であることを保証しませんが、これが実際に行われた POSIX ライクなシステムのいくつかのケースを覚えています。

于 2010-07-08T19:16:09.603 に答える