パソコン活用研究シリコンバレー(C、C++、の活用研究)

FILE構造体

構造体のサンプルとして、stdio.hに準備されているFILE構造体を取り上げてみます。
このFILE構造体は、ファイルの入出力を行う時には必ず使用するものですので、よく理解して
おいて損はないでしょう。FILE構造体を使って、どのようにファイルの入出力をするのかについては
ファイルの入出力」で取り上げているので参照して下さい。


1 FILE構造体の中身

FILE構造体はstdio.hに定義されていますが、コンパイラによって定義のされ方がすこしづつ違います。
まず、MS-Cのものを見てみます。

extern FILE {
char *_ptr;    /*現在ファイルを読み書きしている位置(=ファイルポインタ)*/
int _cnt;     /*ファイルポインタからファイルの最後までのデータ数*/
char *_base;  /*バッファの位置(先頭アドレス)*/
char _flag;   /*ファイルにエラーがおこったかどうかのフラグ*/
char _file;    /*現在のファイルは何番目にオープンされたか(=ファイルディスクリプタ)*/
} _iob[_NFILE]

実際にファイル操作をする時は、fopen, fclose, fgetc, fputc と言ったC言語に用意された関数を使う
ので、自分のプログラム上で直接上記のFILE構造体の各メンバーを参照することは、ほとんどないでしょう。
しかし、各関数は上記のようなメンバーを参照しながら、実際のファイル操作を行っているわけです。

では、他のコンパイラのFILE構造体の定義をみてみましょう。
LSICのものです。
typedef struct {
char mode;     /* file mode R, W, R/W */
char *ptr;      /* next character position  =ファイルポインタ*/
int rcount;      /* number of characters left  ファイルポインタからファイルの最後までのデータ数*/
int wcount;     /* number of rooms left */
char *base;     /* location of buffer  バッファの位置(先頭アドレス)*/
unsigned bufsiz;   /* size of bufer  バッファサイズ*/
int fd;         /* file descriptor  ファイルディスクリプタ*/
char smallbuf[1];  /* used for buffer when unbufferd */
} FILE;

ながめてみるとだいたいMS-Cと同じですね。
smallbufは、現在のバッファにあるデータより、1個前とか1個あとのデータの操作のために使われて
いると思われます。(推測です)

Turbo Cのもの
typedef struct {
short level;    /* fill/empty level of buffer */
unsigned flags;  /* File status flags */
char fd;      /* File descriptor */
unsigned char hold;  /* Ungetc char if no buffer */
short bsize;    /* Buffer size */
unsigned char *buffer;  /* Data transfer buffer */
unsigned char *curp;  /* Current active pointer */
unsigned istemp;  /* Temporary file indicator */
short token;     /* Used for validity checking */
} FILE;

Turbo Cのはメンバー名がMS-Cとはちょっと違っていますが、各メンバーが何の用途に使われているか
だいたい想像できると思います。


2 構造体のメンバーを参照してみる
試しに、FILE構造体の各メンバーを参照してみて、FILE構造体への理解をもう少し深めてみましょう。
LSICのFILE構造体参照用のプログラム(file_str.c)を以下に掲載します。
他のコンパイラのもも、ちょとしたアレンジで作成できるはずです。

/* file_str.c   File構造体の表示  for LSIC*/
#include <stdio.h>
#include <stdlib.h>
main(argc,argv)
int argc;
char **argv;
{
FILE *fp;
int c,cc;
if(argc !=2) exit(0);
if((fp=fopen(argv[1],"rb"))==NULL)
{printf("Cannot open File \n"); exit(1);}
for(;;)
{
cc=fgetc(fp);
printf("Character :%c\n",cc);
printf("ptr       :%08lx\n",fp->ptr);
printf("*ptr      :%02x  %c\n",*fp->ptr,*fp->ptr);
printf("rcount    :%04x\n",fp->rcount);
printf("base      :%08lx\n",fp->base);
printf("*base     :%02x\n",*fp->base);
printf("bufsiz    :%04x\n",fp->bufsiz);
printf("fd        :%04x\n",fp->fd);
printf("smallbuf  :%02x\n",fp->smallbuf[1]);
c=getchar();
if(c==32) break;
}
fclose(fp);
}

簡単なコードなので、コードについては解説しませんが、表示している各項目の意味は以下の通りです。
Character  fgetcで読み込んだデータをキャラクタ表示したものです。
ptr      ファイルポインタ(アドレス)。LSICでは読み込まれたデータの次のデータが格納されている
        アドレスをさしています。
*ptr     次のデータ (すなわち、次のCharacterで表示されるものと同じです)キャラクタコードと
       キャラクタを表示します
rcount    残りのデータ数
base     ファイルバッファの先頭アドレス
*base    ファイルバッファの先頭にあるデータ(=最初のデータ)
bufsiz    バッファサイズ
fd      ファイルディスクリプタ。通常は標準入出力用に5個のファイルが最初からオープンされている
       ので、通常のファイルは5(=6番目にオープンされたファイル)から始まる。
smallbuf  上述の通り(推測)

なお、wcountは表示してません。(今のところ正確な意味が不明なため。誰か教えてください)
プログラムの終了は、Spaceキー(+[Enter])です。

試しに、file_str.c 自身を読み込んでみました。以下の通りです。


A:\>file_str file_str.c
Character :/      --->これは最初のデータ($019011d6のもの) キャラクタコード$2f
ptr       :019011d7    --->1づつ増える
*ptr      :2a  *    --->次のデータ
rcount    :02b7        --->1づつ減る
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005        --->6番目にオープンされた
smallbuf  :00

Character :*
ptr       :019011d8
*ptr      :20
rcount    :02b6
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005
smallbuf  :00


Character :
ptr       :019011d9
*ptr      :46  F
rcount    :02b5
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005
smallbuf  :00

Character :F
ptr       :019011da
*ptr      :69  i
rcount    :02b4
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005
smallbuf  :00


Character :i
ptr       :019011db
*ptr      :6c  l
rcount    :02b3
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005
smallbuf  :00

Character :l
ptr       :019011dc
*ptr      :65  e
rcount    :02b2
base      :019011d6
*base     :2f
bufsiz    :0400
fd        :0005
smallbuf  :00


 



TopPage