2.12.1. 低レベル関数への依存性

Table 2.13 は、高レベル関数の低レベル関数への依存性を示しています。 低レベル関数バージョンを独自に定義する場合は、高レベル関数のライブラリバージョンを直接使用できます。fgetc() は、__FILE を使用しますが、fputc() は、__FILEferror() を使用します。

Table 2.13. 入出力依存

下位オブジェクト    高レベル関数    
 fprintfprintffwritefputsputsfscanfscanffreadreadfgetsgets
__FILE[1]xxxxxxxxxxx
__stdin[2]------x-x-x
__stdout[3]-x--x------
fputc()[4]xxxxx------
ferror()[5]xxx--------
fgetc()[6]-----xxxxxx
__backspace()[7]-----xx----

[1] ファイル構造体。

[2] __FILE 型の標準入力オブジェクト。

[3] __FILE 型の標準出力オブジェクト。

[4] ファイルに文字を出力します。

[5] ファイルの入出力中に累積されたエラーステータスを返します。

[6] ファイルから文字を取得します。

[7] ファイルポインタを前の文字に移動します。 __backspace() の再実装を参照して下さい。

低レベル関数の構文については、ISO C リファレンスを参照して下さい。

Note

fgetc()fputc()、および __backspace() を再実装する場合は、fopen() および関連する関数で __FILE 構造体に ARM レイアウトが使用されていることに注意して下さい。 独自バージョンの __FILE 構造体を定義する場合は、fopen() と関連する関数の再実装が必要になる場合があります。

printf ファミリ

printf ファミリは、_printf()printf()_fprintf()fprintf()vprintf() および vfprintf() で構成されます。 これらのすべての関数は、__FILE を内部的に使用し、fputc() および ferror() 関数のみに依存します。 関数 _printf() および _fprintf() は、浮動小数点値をフォーマットできない点を除き、printf() および fprintf() と同じです。

_printf(...) 形式の標準出力関数は以下の関数と等価です。

fprintf(& __stdout, ...) 

__stdout の型は __FILE です。

scanf ファミリ

scanf() ファミリは、scanf() および fscanf() で構成されます。 これらの関数は、fgetc()__FILE__backspace() のみに依存します。 __backspace() の再実装を参照して下さい。

scanf(...) 形式の標準入力関数は以下の関数と等価です。

fscanf(& __stdin, ...)

__stdin の型は __FILE です。

fwrite()、fputs、puts

__FILE の独自バージョン、fputc() および ferror() 関数、__stdout オブジェクトをユーザ定義する場合は、ライブラリの printf() ファミリのすべての関数、fwrite()fputs()puts()、および C++ オブジェクト std::coutをそのまま変更せずに使用できます。手順については、Example 2.24 を参照して下さい。 実用的なファイル処理が必要な場合は、システムルーチンを修正することを検討して下さい。

Example 2.24. printf() と __FILE

#include <stdio.h>	
struct __FILE
{	
    int handle;	
    /* Whatever you need here (if the only file you are using
       is the stdoutput using printf for debugging, no file
       handling is required) */	
};

FILE __stdout;	
int fputc(int ch, FILE *f)	
{
    /* Your implementation of fputc */	
    return ch;	
}
int ferror(FILE *f)	
{   
    /* Your implementation of ferror */	
    return EOF;	
}
void test(void)	
{
    printf("Hello world\n");  /* This works ... */	
}

デフォルトでは、fread()fwrite() は ARM ストリーム実装の一部である高速ブロック入出力関数を呼び出します。 ARM ストリーム実装を使用せず、代わりに独自の __FILE 構造体を定義する場合、fread()fwrite() はブロック入出力関数ではなく fgetc() を呼び出します。 この実装については、メインサンプルディレクトリの ...\emb_sw_dev\source\retarget.c も参照して下さい。

fread()、fgets()、gets()

関数 fread()fgets()gets() は、fgetc()ferror() に対するループとして実装されます。 それぞれに FILE 引数が内部的に使用されます。

独自の __FILE__stdingets() 用)、fgetc()ferror() を実装する場合は、これらの関数および C++ オブジェクト std::cin をライブラリから直接使用できます。

__backspace() の再実装

関数 __backspace() は、scanf ファミリの関数によって使用されます。 この関数を直接呼び出すことはできませんが、fgetc() レベルで stdio 引数をターゲット変更する場合には再実装できます。

この関数のセマンティクスは以下のとおりです。

int __backspace(FILE *stream);

__backspace(stream) は、ストリームから文字を読み出した後に呼び出す必要があります。 この関数は、ストリームから読み出された最後の文字をストリームに返し、同じ文字がストリームから再度読み出されるようにします。 つまり、scanf によってストリームから読み出されたが不要になった文字(scanf の動作が終了する理由となった文字)が、その次の関数でストリームから正しく再読み出しされるようにします。

__backspaceungetc() とは異なります。 これは、scanf ファミリの関数の終了後に単一の文字を確実に返すための関数です。

__backspace() によって返される値は 0(成功)または EOF(失敗)のいずれかです。 EOF は、ストリームから文字が読み出されなかった場合など、誤った方法で使用された場合にのみ返されます。 正しく使用されている限り、__backspace() は必ず 0 を返す必要があります。これは、scanf ファミリの関数がエラー復帰をチェックしないためです。

__backspace()ungetc() との関係は以下のとおりです。

  • ストリームに __backspace() を適用し、同じストリーム内の文字に ungetc() を適用した場合、それ以降の fgetc() 呼び出しでは ungetc() によって返された文字を最初に返し、次に __backspace() によって返された文字を返す必要があります。

  • ungetc() でストリームに文字を返し、その文字を fgetc() で読み出してから後退する場合、fgetc() によって読み出される次の文字は、ストリームに返された文字と同じ文字である必要があります。 つまり、__backspace() 処理は fgetc() 処理を取り消す効果を持っている必要があります。 ただし、__backspace() 呼び出し後に再度 ungetc() を呼び出した場合にそれが成功する必要はありません。

  • ストリームに対して文字が ungetc() された直後に、読み出しが実行されることなく、さらにもう 1 文字が __backspace() されるような状況はありません。これは、__backspace() の呼び出しが、必ず fgetc() の呼び出し後に実行される必要があるため、その呼び出しのシーケンスが不正となるためです。 __backspace() を実装する際には、このような状況を想定する必要はありません。

Copyright © 2007 ARM Limited. All rights reserved.ARM DUI 0349AJ
Non-Confidential