2016-04-29 16 views
2

次のプログラム:C標準はstdoutからの入力を読み込むための動作を指定しますか?

#include <stdio.h> 

int main() 
{ 
    char s[10] = ""; 
    fprintf(stdout, "%s", "hello"); 
    fscanf(stdout, "%6s", s); 
    perror(NULL); 
} 

出力Bad file descriptor。しかし、C11 draft standardのセクション7.21は、stdoutfscanfに渡されることが許可されているかどうかについては何も言わないようです。これは未定義の動作ですか?明示的(標準的な見積もりを与える)または暗黙的に(省略によって)?

+8

コードはCではなく、Cです。 –

+0

ダウンリストの場合:コードをCに書き直してください。気にしません。 * Cの標準に関する問題、またはC++の標準とCのライブラリが組み込まれているという事実は変わりません。 – sigh

+5

** stdout **は入力ストリームではなく出力ストリームなので、入力ストリームを入力することはできません。未定義の動作です。 **あなたのアプリケーションに**標準出力**を行い、** stdin **からそれを読んでください。 – LPs

答えて

4

仕様(ISO/IEC 9899:2011(E)、§7.21)は、出力関数に渡される入力ストリームまたは入力関数に渡される出力ストリームに実際には何の制限も言及していません。仕様の唯一の制限は、fflushに渡されるストリームが出力ストリームでなければならないことです。

+0

私は人々が正解を上回っていることを嬉しく思っています。 – sigh

+4

ここではわかりません。 7.21.3p11では、バイト入力関数は 'fgetc'を連続して呼び出すことによって文字を読み込み、7.21.7.1p2の' fgetc'の仕様は '' stream''が指す入力ストリームに対して '' UB私に。 –

+0

@ T.C。正直言って私は入力関数に関して出力ストリームの明示的な言及をほとんど探していました。少し曖昧ですが、 'fgetc'で出力ストリームを使うと*未定義*で、未定義ではないと言いたいと思います。私は 'fread'と' fgets'をもっとよく調べましたが、彼らは "入力"(または出力)ストリームについては何も言いません。 –

2

§4/ 2(WG14 N1570引用):

未定義の挙動は、他の単語「」未定義の動作「」によって、または動作のいずれか 明示的な定義を省略することにより、この国際 規格で示されています。

§7.21.3/ 11

バイト入力関数はfgetc関数へ 連続呼び出しであるかのように、ストリームから文字を読み取ります。

(およびfscanfは、バイト入力関数です.7.2.1/5)。

§7.21.7.1:

fgetc機能

概要

#include <stdio.h> 
int fgetc(FILE *stream); 

説明

入力ストリームのエンドオブファイルインジケータはstreamによって を指摘している場合に設定し、次の文字が存在していない、fgetc 関数はintに変換unsigned charとしてその文字を取得し、関連進み ストリーム(定義されている場合)のファイル位置インジケータ。

戻り

ストリームのend-of-fileインジケータが設定されている場合、またはストリームがファイルの終わりにある 場合、用ファイル終了インジケータストリーム が設定され、fgetc関数がEOFを返します。そうでない場合、fgetc 関数は、入力ストリームの次の文字を に指してstreamで返します。読み取りエラーが発生すると、 ストリームのエラーインジケータが設定され、fgetc関数はEOFを返します。 [脚注省略]

fgetcの指定では、「streamが指し示す入力ストリーム」と繰り返し指定されています。 streamが入力ストリームを指し示すという暗黙的な要求があるか、またはstreamが入力ストリームを指していないときに標準を省略して動作を指定するという2つの方法で読み取ることができます。

最初のケースでは、非入力ストリームをfgetcに渡すと、その要件に違反し、未定義の動作になります(§7.1.4/ 1も参照してください。これは、関数のドメイン外の値"); 2番目のケースでは、非入力ストリームをfgetcに渡すと、その場合の標準ではfgetcの動作については何も言及していないため、省略によって未定義の動作になります。だから私はfgetc(not_an_input_stream)は未定義の動作を引き起こすと主張するだろう。

fgetc(not_an_input_stream)が未定義の振る舞いの場合は、fscanf(not_an_input_stream, /*...*/)です。後者は、前者を呼び出すことによって文字を読み取るように指定されています。

関連する問題