1.16 C ライブラリで高レベルライブラリ関数の直接使用を有効化するための低レベルライブラリ関数の再定義

__FILE の独自バージョン、fputc() および ferror() 関数、ならびに __stdout オブジェクトをユーザ定義する場合は、ライブラリの printf() ファミリのすべての関数、fwrite()fputs()puts()、および C++ オブジェクトの std::cout をそのまま変更せずに使用できます。

以下の例は、この方法を示しています。ただし、実用的なファイル処理が必要な場合は、これらの低レベルのライブラリ関数ではなく、システム入出力関数の修正を検討して下さい。
これらの例に示す関数をすべて再実装する必要はありません。アプリケーションに使用する関数のみを再実装して下さい。

printf() のターゲット変更

#include <stdio.h>
struct __FILE
{
  int handle;
  /* ここで必要なものを記述。使用しているファイルが */
  /* デバッグ用の printf() を使用する標準出力のみである場合、 */
  /* ファイル処理は不要。*/
};
/* FILE は stdio.h の typedef’d。*/
FILE __stdout;
int fputc(int ch, FILE *f)
{
  /* fputc() の実装。*/
  return ch;
}
int ferror(FILE *f)
{
  /* ferror() の実装。*/
  return 0;
}
void test(void)
{
  printf("Hello world\n");
}

fputc() のエンディアンに注意して下さい。 fputc() では、int パラメータを指定しますが、1 文字のみが含まれます。その文字が整数変数の上位バイトと下位バイトのいずれに含まれるかは、エンディアン方式によって決まります。次のコードサンプルを実行すると、エンディアン方式に関する問題を回避できます。
extern void sendchar(char *ch);
int fputc(int ch, FILE *f)
{
  /* 例えば、LCD に文字を書き込む */
  char tempch = ch;  // temp char でエンディアン問題を回避
  sendchar(&tempch); // sendchar(&ch) はどこでも機能するわけではない
  return ch;
}

cout のターゲット変更

ファイル 1:再実装の必要な関数だけを再実装します。
#include <stdio.h>
namespace std {
  struct __FILE
  {
    int handle;
    /* ここで必要なものを記述。使用しているファイルが */
    /* デバッグ用の printf() を使用する標準出力のみである場合、 */
    /* ファイル処理は不要。*/
  };
  FILE __stdout;
  FILE __stdin;
  FILE __stderr;
  int fgetc(FILE *f)
  {
    /* fgetc() の実装。*/
    return 0;
  };
  int fputc(int c, FILE *stream)
  {
    /* fputc() の実装。*/
  }
  int ferror(FILE *stream)
  {
    /* ferror() の実装。*/
  }
  long int ftell(FILE *stream)
  {
    /* ftell() の実装。*/
  }
  int fclose(FILE *f)
  {
    /* fclose() の実装。*/
    return 0;
  }
  int fseek(FILE *f, long nPos, int nMode)
  {
    /* fseek() の実装。*/
    return 0;
  }
  int fflush(FILE *f)
  {
    /* fflush() の実装。*/
    return 0;
  }
}
ファイル 2:再実装した関数を使用して「Hello world」を出力します。
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
  cout << "Hello world\n";
  return 0;
}
デフォルトでは、fread()fwrite() は ARM ストリーム実装の一部である高速ブロック入出力関数を呼び出します。ARM ストリーム実装を使用せず、代わりに独自の __FILE 構造体を定義する場合、fread()fwrite() はブロック入出力関数ではなく、fgetc() を呼び出します。
関連する概念
1.14 C ライブラリ printf ファミリ関数
1.15 C ライブラリ scanf ファミリ関数
1.17 C ライブラリ関数 fread()、fgets()、および gets()
1.18 C ライブラリでの __backspace() の再実装
1.19 C ライブラリでの __backspacewc() の再実装
1.20 C ライブラリでのターゲットに依存するシステム入出力関数の再定義
関連する参考文書
1.12 C および C++ ライブラリでの入出力関数のカスタマイズ
1.13 C および C++ ライブラリ内での低レベル関数のターゲット依存関係
非機密扱いPDF file icon PDF 版ARM DUI0808CJ
Copyright © 2014, 2015 ARM.All rights reserved.