ポインタ - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年5月号
47件見つかりました。

1. 月刊 C MAGAZINE 1990年5月号

わけて、す。このようなポインタの機能は , 「 C 言語はアセンプラなみの細かい記述がて、 きる」といわれるゆえんて、す。 先に説明したように , ポインタは変数を 使った表現を , さらにコンピュータ側に寄 せて原始的に表現したものて、す。て、すから ァータ値 ポインタと変数とは相互に互換性がありま す。ここて、は変数として a, ポインタとして p というものを用意し , そのようすを Fig. 5 て、説明していきます。 変数 a という立場て、見たとき , メモリ上て、 は Fig. 5 ー 1 のような構成になっています。た だたんに、、 a 〃というと変数 a の値 ( 変数値 ) が 参照されます。 Fig. 5 ー 1 の場合は 10 て、す。 変数 a の箱がどこにあるのか ( 変数 a の在 処 , 変数 a のアドレス ) については , このま まて、はユーザは知ることがて、きません ( Fig. 5 ー 1 て、は ? ? ? ? 番地になっている ) 。この変 数のアドレスを取り出すのが「アドレス取得 演算子 ( あるいはアドレス演算子 ) & 」という単 項演算子て、す。実際には , &a となります。これが C 言語における変数 a の アドレスて、す。たとえばポインタ p に変数 a のアドレスを代入するには , Fig. 5ー1 変数 a P & a アドレス ? ? ? ? 番地 ? ? 番地 ポインタロ 00 番地 アドレス Fig. 5ー2 変数 a のアドレス ( ? ? ? ? 番地 ) は 変数値 ( 1 のは ? ? ? ? は値が不定なことを示す ( 注 ) 変数 a の値は 10 とする メモリ 変数値 として取り出すことができる メモリ とするだけて、す。 ・ポインタ p 今度はポインタ p という立場て、調べてみま しよう。メモリ構成は Fig. 5 ー 2 のようになっ ています。単に、、 p 〃とするとポインタ p の 値すなわちポインタ p の指すアドレスにの 場合は 1000 番地 ) を取り出すことがて、きま す。しかしこのアドレスに格納されている データ値を知るには , 「間接演算子 * 」を用 いなければなりません。これもやはり単項 演算子て、す。 * P とすることによってポインタ P が指すアドレ スの値を取り出すことがて、きます。さらに 変数 a にポインタ p の指すアドレスの値を代 入するには , * P まり変数 a の値そのものになります。 これは「変数 a の , アドレスの , 指す値」 , つ ちなみに次のものは何を示すて、しようか ? とします。 ( 注 ) ポインタロの指すアドレスは 10 番地とする ? ? ? ? は値が不定なことを示す ポインタロの指すアドレス ()0 囲番地 ) は ポインタロの指すアドレスの値 ( ? ? ? ? ) は *D 124 CMAGAZINE 19 5 として取り出すことができる Tbl.1 ポインタ演算子 & ( アドレス演算子 ) * ( 間接演算子 ) 意味 変数のアドレスを取り出 す & ( a 十 l) のような使い方 はまちがい ポインタのさすアドレス より値を取り出す ポインタ変数にのみ有効

2. 月刊 C MAGAZINE 1990年5月号

五ロ はじめて学ぶプロクラー ニンク 匚。司 った段階て、メモリの状態は Fig. 7 ー 1 のよ int * p ; うになっており , 領域が確保されてい 「 * 」は前節て、て、てきた , データ値を求める ます 間接演算子て、す。「ポインタ、、 p 〃の指す、、値〃 ② 12 行目 ( a = 10 ; ) て、 c れ ar 型変数 a に 10 は、、 int 型〃」を意味します。同様に「 char 型 これらのポインタの演算を行うためには , が代入されます (Fig. 7 ー 2 ) データを指すポインタ p 」の宣言は , やはりそのポインタ用の領域をメモリ上に ③ 13 行目 ( p = & a ; ) て、は変数 a のアドレス char * p ; 確保し , その値を記憶しなければなりませ 値を取ってきて ( アドレス取得演算子を となります。一般的にポインタ宣言の書式 ん。というのもポインタも変数のひとつな 使っています ) , ポインタ p に代入して は , このあたり慣れないと混 います。実行が終わった段階て、ポイン のて、すから・・ テータ型 * ポインタ名 乱するかもしれませんね。ポインタは , 記 タ p は a のアドレスを指すようになりま となります。ポインタの配列を取りたいと 憶しているデータが別の変数のアドレス ( 物 きには「ポインタ名 [ 要素数 ] 」とします。 す (Fig. 7 ー 3 ) 理的なアドレスという場合もある ) て、あると ④ 14 行目 ( x = * p ; ) て、はポインタ p の指 いうだけて、 , 変数の一種て、あることに変わ すアドレスから char 型のデータを取っ てきて ( 間接演算子を使っています。取 りないのて、す。 8 ー 2 て、は p はポインタて、あるとして説明し ってきた値は 10 て、す ) それを char 型変数 こまて、説明をして , ようやくまとまっ ましたが , 実際にはポインタを使う前に「 P x に代入しています。実行が終わった段 たプログラムを記述て、きるようになります。 する必要があ はポインタて、ある」と旦 階て、は Fig. 7 ー 4 となっています ポインタを使ったごく簡単な例を List1 に示 ります。しかし , ポインタ型などというデ 結局これらの動作により a の値が x にコピ します。動作が理解て、きるて、しようか ? ータ型も , それを表す型宣言子も存在しま ーされました。しかし直接代入するのて、は 蛇足かも知れませんが , Fig. 7 を使って説 せん。仮にあったとしてもこれまて、に述べ なく , ポインタ p を介してコビーされたとい てきた , 変数とポインタの互換性がとれな 明してみましよう。 うことが新鮮て、すね。そして , 変数 a が実際 ① 10 行目 (char * (;) まて、実行が終わ 何番地に用意されているのか , くなってしまいます。というのは変数とい という具体 っても char, int, float, double などと種 類がたくさんあり , 「おのおのデータのサイ ズが異なるからて、す」 (TbI.2)o したがって , たとえばポインタ P が同じと ころを指していても , データ型によって取 り出すデータのバイト数が異なります。 Fig. 6 この例て、は , にこの説明をしました。 → 1000 番地のデータ char 型データ を取り出す → 1000 , 1001 番地の int 型データ データを取り出す という使い分けが必要になります。ポイン タとひと口にいっても , 「 char 型データを取 り出すポインタ」や「 int 型データを取り出す ポインタ」といった使い分けが必要て、す。 「 c れ ar へのポインタ」とか「 int へのポインタ」 といういい方をする人もいます ( もちろん 「 float へのポインタ」や「 double へのポイン タ」などもちゃんと存在します ) 。 これらの事柄をふまえたうえて , 「 int 型デ ータを取り出すポインタ 0 」の宣言は次のよ うになります。 P 川 00 用囲番地 1001 番地 ha 「型データ int 型テータ ( 注 ) この例では cha 「型は 1 バイト . int 型は 2 バイトのサイズをもつ場合を示す TbI. 2 変数の基本テータ 型宣言子 バイト長 意味 1 バイト整数型 整数型 ( 注 1 ) 単精度浮動小数点型 ( 注 2 ) 倍精度浮動小数点型 float 型の 2 倍 注 1 CPU による。一般的にいってビットのコンビュータでは給ビット , つまり 2 バイト。 MS-DOS 上ではおもに 2 バイト 注 2 CPU による。パソコンクラスでは 4 バイトが一般的 Char i nt float double 1 はじめて学ぶ C プログラミング 125

3. 月刊 C MAGAZINE 1990年5月号

ラプ 9 リ ラタ乙 こしてから使用している ( List1 に実際の例を 示す ) 。 List List プリンタ出力例 標準入出力 ファイル 標準入出力ファイルというのは , MS - DOS が立ち上げ時に周辺デバイスをファイルと して扱うことがて、きるように割り当てたも のを指している ( Tbl. 2 参照 ) 。キーポードや CRT, またはプリンタなどのハードウェア を一般のファイルのように扱おうという考 え方は , UNIX からの流れて、ある。 List2 を見てもらいたい。これはヘッダフ ァイル stdio. h の中て、マクロ定義されている 関数て、 , この #define 文による定義は , MS -C も TurboC もどちらも同じて、ある。 getchar( ) 関数は getc ( ) 関数に展開され , しかも標準入出力に stdin が指定されてい る。プログラミングとしては , 標準入出力 デバイスをファイルのように扱うことがて、 きるのて非常に楽て、ある。もっと簡単な使 用方法はプリンタデバイスて、ある。プリン タに文字を出力するには , たんに List3 のよ うにすればよい このように , 標準入出力ファイルの使い 方はいろいろなプログラミング方法に応用 しやすいようにて、きている。ただ , プリン タのように出力だけしかて、きないものや , COM のように入力しかて、きないものもある のて、 , オープンする際のオプションには注 意しなくてはならない #define getchar() getc(stdin) #define putchar(c) putc((c) , stdout) FILE *fp; fopen( ” PRN" fputs("HeIIo world ! " , (p) : TbI.2 ファイル ティスクリプタ 0 1 2 3 4 ファイル ホインタ ファイル テパイス 標準入力 標準出力 標準工ラー 標準補助ポート入出力 標準プリンタ stdin キーボード CRT CRT COM ボート プリンタ stdout stderr stdaux stdprn LiSt fopen 関数使用サンプルプログラム fopen. c 1 : 2 : このプログラムの簡易機能 3 : 新規ファイルを作成して新たな行を書き込む。 4 : 書き込まれたファイルをまた読み込んで表示させる。 5 : 6 : Compiler is MSC, or TurboC 7 : 8 : 9 : 10 : #include く stdio. h> 11 : #include く conio. h> 12 : #include く stdlib. h 〉 13 : 14 : i nt type ( vo i d ) : 15 : 16 : F ILE *f p : 17 : 18 : VO i d ma i n ( VO i d ) 20 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 32 : fopen, freopen, fclose fopen ( ) 関数は , オープンしたファイルと fopen ( ) 関数が返してくるファイルポインタ とを密接に結びつけている。以後はファイ ルと結合されたこのファイルポインタがす べての操作の対象となる。なお , このファ イルポインタは , オープンしたファイルの int i; fopen("work. txt" fprintf(stderr, ex i t ( "File open error !Yn"); for (i fprintf(fp, i 十十 ) ” Newl ine X2d is add. Yn ” C プログラマのためのランタイムライプラリ入門 79

4. 月刊 C MAGAZINE 1990年5月号

いうように使い分けることが可能て、す。さ て List2 の結果はどうなりましたか ? この プログラムの動作がわかりますか ? わか りにくかったら Fig. 7 のようなメモリの状態 図を書いて考えるとよいて、しよう。 * p を変数として使う場合の注意をここて、 申し上げておきましよう。 List3 を実行して みてください。何が起こりましたか ? ①コンパイル時に警告がて、た ②実行したら暴走した ③正しく実行て、きた ④やるたびに結果が異なる など , わけのわからないことが生じます。 何回やっても正しく実行て、きる人もあるか もしれませんが , この List3 のプログラムは 「まちがったプログラム」なのてす。どこ がまずいかおわかりになりますか ? 「 * p は変数として使えるんだからかまわ んじゃないか。 List4 の a を * P に置き換えた だけだぞ」という考えの方もいらっしやる かもしれません。確かに List4 は正しく動作 する正しいプログラムてす。ポインタとし て宣言された P を変数として使うのだから , このプログラム中の a をすべて 0 に置き換 というのも無理からぬ考えて、 えればよい す。 こて、 8 ー 1 ー 2 の記述を思い出してくださ 「変数を使った表し方て、は , データを置く アドレスをユーザがいちいち管理する必要 はありません。このアドレスはコンパイラ ( ないしはインタブリタ ) が決めて管理して くれます。ユーザは変数のデータ値を自由 に変更することが可能て、す。対してポイン タを使った表し方を用いれば , データを置 くアドレスの決定権をもユーサはもっこと ができる」わけて、す。 「データを置くアドレスの決定権をもユー ザはもつ」 , 逆にいうとユーザがきちんとア ということなのて、 ドレス管理をしなさい 的な話はさほど重要て、はなく , ポインタ p が るときに , * p を int 型変数として使うこと す。 List3 のメモリイメージを Fig. 8 に示した 変数 a のアドレスをヾ指している〃という考 がて、きるのて、す。ポインタとして宣言され ように , 宣言された P は値が不定て、す え方に意味があります。 ている p を変数として使いたいときには * P ( ? ? ? ? になっている ) 。不定とはいえ何 さらに List2 のような使い方もて、きます。 を , そして実際アドレスをポイントする必 かしら値が入っているわけて、すから , P はそ p が int 型へのポインタとして宣言されてい 要がて、てきたときに p としてポインタを , と 126 CMAGAZINE 19 5 ポインタの例 ( 1 ) List 1 2 : 4 : 5 : #include く stdio. h> 6 : 7 : void main(void) 9 : Char a, X : char *p; = 10 ; 14 : printf(" い s t 1 ポインタの例 ( 1 ) / * これはただの char 型変数です / * char へのポインタ p / * char 型の a に 1 0 を代入 / * ポインタ p に a のアドレスを代入 * / / * p の指す値を x に代入 = XdYn ” X ポインタの例 2 Li st 2 2 : 4 : 5 : #include く stdio. h> 6 : 7 : void main(void) 9 : / * これはただの i nt 型変数です int a; / * int へのポインタ p int *p; 12 : / * a のアドレスを p に代入 / * p の指すアドレスの内容を 1 0 にする = 10 : printf("*p ニ %d, a ニ %d\n" List2 ポインタの例 ( 2 ) まちがったポインタの使用例 い st3 間違ったポインタの使用例 List. 3 2 : 4 : 5 : #include く stdio. h> 6 : 7 : void main(void) 9 : int *p; printf("*p = %dYn" 13 :

5. 月刊 C MAGAZINE 1990年5月号

五ロ ニ - 一口 はじめて学ぶプログラー ニング データの代入・参照をユーザに解放しまし するアドレスに値 10 を入れる としました。これにより Fig. 2 のような状態 これらは立場が違う ( 人間側かコンヒ。ュータ になります。 た。 側か ) だけて、 , 実態は同じことを意味してい 変数を使った表し方て、は , データをおく こて、 , 変数 a に値 10 を代入するというの アドレスをユーザがいちいち管理する必要 は人間側の概念て、す。そもそも変数自体が ます。したがって , 人間によって作られた概念て、す。この代入 変数 a ←→ポインタ a のポイントす はありません。このアドレスはコンパイラ という操作はコンピュータの側からすると るアドレス ( ないしはインタブリタ ) が決めて管理して どのように処理されているのて、しようか。 という関係が成り立ちます。 くれます。ューザは変数のデータ値を自由 変数といわれてもコンピュータ側にその概 人間が「変数 a に 10 を代入する」ということ に変更することが可能て、す (Fig. 4ー1)。それ 念はありません。コンピュータにて、きるこ に対して , ポインタを使った表し方を用い は , コンヒ。ュータにとっては「ポインタ a の とは値 ( この場合 10 ) をメモリ上に記憶する ポイントするアドレスに 10 を入れる」という れば , データをおくアドレスの決定権をも だけて、す。メモリ上のどこにこの値を記憶 ことて、す。また「変数 a の値を取り出す」とい ューザはもっことがて、きるわけて、す ( Fig. 4 するかというと , 、、人間が変数と呼んて、いる うことは「ポインタ a のポイントするアドレ ー 2 ) 。したがってポインタ a の値を 1001 にす a という記号の指すアドレス〃に記憶しま スにしまってある値を取り出す」ということ ると , 同じポインタ a を用いていながら , そ す。今まて、変数とは値を入れる箱として理 のデータ値は 1001 番地の内容となります。 になります。 解していましたが , コンピュータ側から見 C 言語て、は , これまて、コンヒ。ュータ側の立 つまりポインタ a の値を変えることによっ れば , あるメモリにつけてある単なる名前 場として説明してきた , ポインタを使った て , どの番地のデータて、もアクセスて、きる ( 記号 ) にすぎなかったわけて、す。ちょっと 以下にまとめてみましよう。 〇変数 人問側 : 値をしまっておく箱 コンヒ。ュータ側 : メモリ上のあるアド レスにつけてある名前 ( 記号 ) 〇代入 ( a = 10 ) 人間側 : 変数 a に値 10 を入れる コンピュータ側 : 記号 a の指し示すアド レスに値 10 を入れる 「記号 a の指し示すアドレス」というのは言葉 を換えれば「 a という名前のついているメモ リアドレス」のことてす ( Fig. 3 参照 ) 。 8-1-2 ポインタとは何か 「指し示す」や「アドレス」という言葉がて てきましたね。いよいよ近づいてきました。 「指し示す」という言葉をカタカナて表現 すると「ポイント (point) する」になります。 そして「ポイントするもの」を「ポインタ (pointer) 」といいますから「記号 a 」も「ポイン タ a 」と読み換えられます。このことを踏ま えて先のヾ代入〃は次のような表現にいい 換えられます。 〇代入 ( a = 10 ) 人問側 : 変数 a に値 10 を入れる コンピュータ側 : ポインタ a のポイント Fig. 4ー1 メモリ 変数表現 アドレス 変数 a x x x x 番地 x x x x 番地 データ値 ( 注 )xxxx 番地は , ユーサにはどこにあるかわからないことを示す Fig. 4 ー 2 ポインタ表現 アドレス ポインタ a 00 番地 メモリ l- -- ・一一 1 000 番地 データ値 ( 注 ) 1000 番地はユーサが決めたアドレスを示す はじめて学ぶ C プログラミング 123

6. 月刊 C MAGAZINE 1990年5月号

freopen ■機能要約ストリームをファイルに置き換える #include く stdio . h> ・用法 freopen( path, type, stream ) ; ■弓ー数 const char * path : オープンするファイルのバス名 : アクセス許可設定 , 以下の記号定数を設定 cha r * type CM S-C] : アクセス許可設定 , 以下の記号定数を設定 const char * type CTurboC] : ファイル構造体へのポインタ 既存のファイルを読み込みのためにオープンする w' 書き込みのために空のファイルをオープンする ( ファイルが存在すれば , 内容は失われる ) ファイルの最後に追加するためにオープンする ( ファイルが存在しなければ , 新たに作成する ) ” r 十” 既存のファイルを読み込み・書き込み両用にオープンする 空のファイルを読み込み・書き込み両用にオープンする ( ファイルが存在すれば , その内容は失われる ) 読み込み・追加両用にファイルをオープンする ( ファイルが存在しなければ , 新たに作成する ) ほかに , 次の文字を type 文字列に付加することによって , 復改文字の変換モ ードを指定できる テキストモードでオープンする ( ANSI 標準ではない ) ( 入力時には CR / LF が LF に , 出力時には LF が CR / LF に変換される ) バイナリモードでオープンする ( CR / LF の変換は行われない ) ・戻り値 FILE* : 新たにオープンしたファイルへのポインタ ・エラー NULL 変換される引数のサイズの指定 [d, i,o,x,X] short int short unsigned int [d,i,o,x,x] long int long unsigned int 引数の型指定 ( ptr ) はポインタ指定を表す int (ptr) 符号つき 10 進整数 (ptr) 符号なし 10 進整数 unsigned int int (ptr) 符号なし 8 進整数 int (ptr) 符号なし 16 進整数 符号つ ong 型 10 進整数 long (ptr) unsigned long (ptr) 符号ない ong 型 10 進整数 符号な Ulong 型 8 進整数 long (ptr) 符号ない ong 型 16 進整数 long (ptr) 符号っき 8 / 10 / 16 進整数 int (ptr) 符号つき 8 / 10 / 16 進整数 int (ptr) 符号っき浮動小数点数 float ( ptr) 符号つき浮動小数点数 float (ptr) 符号つき浮動小数点数 float (ptr) cha (ptr) 単一の文字 最後の " \ 0 " を含めた長さを格納で 文字列 (ptr) きる文字配列へのポインタ ストリームやバッフアに書かれた文 字数が指定変数に格納される 引数のアドレスを xxxx : yyyy 形式で void far (ptr) 格納 prefix type 0 x 0 X FILE * stream int (ptr) b fseek ・機能要約ストリームのファイルポインタを移動する #include く stdio . h 〉 ■用法 fseek ( stream, offset, origin) ; ー引数 FILE *stream : ファイル構造体へのポインタ : 引数 origin からのバイト数 long Offset int origin : 先頭の位置 , 以下の記号定数から選択 ファイルの始め 現在のファイルポインタの位置 ファイルの終わり fscanf ・機能要約ストリームからデータをフォーマットして読み出す #include く stdio . h> ■用法 fscanf( stream, format く argument. ■弓ー数 FILE *stream: ファイル構造体へのポインタ const char * format : 書式制御文字列 ■戻り値 int : 変換後代入されたフィールドの個数 ( 代入されていないフィールドの個数は含まれない ) ■工ラー int EOF : ファイルの終わりを読もうとした : フィールドがひとつも割り付けられなかった int 0 ■注意引数は , format に対応した型の変数へのポインタでなければならない fo 「 mat の書式・機能は , 以下のとおりである Cfscanf 書式一覧 ] ・ fscanf の書式指定は " % " に続く文字列で表現される ・書式指定の形式は以下のとおり ( 【】内部は省略可 ) % (flags 】【 width 】【 modell 【 prefix 】 type 意味 ( ロ内部は , それぞれの type によって意味が異な る場合を示す ) 次のフィールドは , type に変換されるが , 格納は行わ れない 入力する文字数の下限を指定 ( 数字で表記 ) sm 訓モデルでは , 引数に fa 「ポインタをとる場合に指 定 compact, midiam,large, huge モデルにおいて , 引数に near ポインタをとる場合に指定 SEEK SET SEEK CU R SEEK END ー戻り値 0 : 正常終了 i nt ・エラー int ! 0 ftell フィールド文字 ・機能要約ストリームのファイルポインタの位置を , 先頭からのオフセット で返す #include く stdio . h 〉 ・用法 ftell( stream ) ; ・引数 FILE *stream : ファイル構造体へのポインタ ■戻り値 long : ファイルポインタのオフセット値 ■工ラー long ー 1 L ags width model 84 CMAGAZINE 19 5

7. 月刊 C MAGAZINE 1990年5月号

ポインタその 1 匚ら司 五ロ はじめて学ぶ 0 プログラー ニング 第 8 回高木聡 / 山崎信行 いよいよこれから 2 回にわたって , ポインタについて学びます。何もい よいよなどと気張ることもないのですが , C 言語を学ぶうえでポイン タかひとつの大きな壁になっています。私たちも多少緊張してしま います。皆さんがとつつきにくいということのないように , できる だけわかりやすい説明を心かけます。 スを指し示しているもの [ 変数 ] 」というこ とになりましようか。これて、もわかりにく いかもしれませんね。そこて、もっと詳しく 見ていきましよう。 度簡単に触れてみます。細かい話は 1989 年 11 月号を参照していただき , こて、はポイ ンタの理解のために必要な事項を復習しま 「ポインタとは何か」を C 言語の参考書て、 変数とは、、値の入れもの ( 箱尸として考 8-1-1 変数の復習 調べると , 「ほかの変数のアドレスをもつ変 えることがて、きました。そしてこの箱は使 数」と書かれています。慣れない人にはちょ う則に、、変数宣〃によって用意しなくて ポインタは単独て、は , その存在価値はあ っとわかりにくいて、すね。そこて、ポインタ はいけませんて、した。たとえば a という char (pointer) という言葉を辞書て、引くと , ①指 まりありません。多くは普通の変数を指し 型変数をプログラム中て、使いたい場合には , 示して ( ポイントして ) 使われます ( 普通の変 す人 [ 物 ] , ②針 , 指針 , ③大の種類 ( / ) , char a; 数とは変ないい方て、すが , ここて、は int, などとあります。 C 言語て、ポインタとててき と変数宣言しました。これによってメモリ char, float, double といった今まて、によ た場合は①の指すものという意味が適当て、 上に変数 a の値をしまう箱が確保されます くててきた一般的な変数としてご理解くだ (Fig. 1)0 この変数 a に 10 という値を代入す これらをまとめて考えてみると C 言語て、出 さい ) 。 るには , てくるポインタとは , 「ほかの変数のアドレ このように変数の話は重要て、す。もう一 Fig. 2 10 ; a Fig. 3 メモリ メモリ 122 CMAGAZINE 19 5

8. 月刊 C MAGAZINE 1990年5月号

イロ入 putc ー機能要約ストリームに 1 文字出力 ( マクロ定義 ) #include く stdio . h 〉 ■用法 putc (), stream) ; ■引数 intc 書かれる文字 : ファイル構造体へのポインタ FILE * stream ー戻り値 int . 書き出した文字 ・エラー int EOF ■注意 EOF がエラーによるものかどうか調べるには , fe 「 ror を使用 fwrite ■機能要約データ ( 指定バイト長 ) を特定数だけストリームに書き込む #include く stdio . h 〉 ■用法 fwrite ( buffer, size, count, stream ) ; ■弓ー数 const void * buffer : データを格納している場所へのポインタ Size t Size : データ項目ひとつ当たりのバイト数 Size t : 書き出す項目の最大個数 FILE * stream : ファイル構造体へのポインタ ー戻り値 size t : 実際に書かれた全データ項目の個数 ( バイト数ではない ) ・エラー size t : 戻り値が count より小さくなる ー注意 stream のファイルポインタは実際に書いたバイト数だけ進む。 st 「 eam が テキストモードでオープンされている場合は , 復帰 ( CR ) を復帰 / 改行 ( CR / (F) で置き換えるが , この置き換えによる戻り値への影響はない。工ラ ーが発生した場合 , アクセス位置インジケータの値は参照できなくなる fputc ・機能要約ストリームに 1 文字出力する #include く stdio . h 〉 ■用法 fputc( c, stream ) ; ■引数 int c : 出力する文字 FILE *stream : ファイル構造体へのポインタ ー戻り値 int c : 出力した文字自身 ・エラー : 工ラーか EOF ( という値 ) かを判定するためには , fer 「 or int EOF を使用する ■注意 fput, fputchar は putc, putchar と似ているが , マクロ定義ではなく関数で ある getc ・機能要約ストリームから 1 文字読み込む #include く stdio . h 〉 用法 getc ( stream ) ; ■引数 FILE *stream : ファイル構造体へのポインタ ■戻り値 int : 読み込まれた文字 : ファイルの終わり int EOF ・エラー int EOF ・注意工ラーかファイルの終わりかを判定するには , ferro 「関数または feof 関数 を使用する。 getc は関数ではなくマクロとして定義されている rewind ・機肯皀要約ストリームのファイルポインタをファイルの先頭に移動する #include く stdio . h 〉 ・用法 rewind( stream ) ; ・引数 FILE *stream : ファイル構造体へのポインタ ・戻り値 void ■工ラーなし ■注意 fseek( stream, OL, SEEK SET ) とほば同じ ( EOF やエラ ーのインジケー タをクリアする。戻り値がない ) fgetc ー機能要約ストリームから 1 文字読み込む #include く stdio . h 〉 ー用法 fgetc ( stream ) ; ・引数 FILE *stream : ファイル構造体へのポインタ ー戻り値 int : 読み込んだ文字自身 : ファイルの終わり int EOF ■工ラー int EOF : 工ラーかファイルの終わりかを判定するためには , feof または fe or を使用 ■注意 fgetc, fgetchar は getc, getchar と似ているが , マクロ定義ではなく関数 である setbuf ー機能要約ストリームのバッフアを変更する #include く stdio . h 〉 ー用法 setbuf ( stream, buffer ) ; ■引数 FILE * stream : ファイル構造体へのポインタ : ユーザが割り当てたバッファ ( NULL の場合にはバッ char * buffer ファ化しない ) ■戻り値 void ■工ラーなし ■注意 stderr と stdaux はデフォルトではバッフアがないが , これによりバッファ 化が可能 C プログラマのためのランタイムライプラリ入門 85

9. 月刊 C MAGAZINE 1990年5月号

TbI.1 高水準ファイル入出力関係のランタイムライプラリ ( 一部 ) の比較表 MS-C Tu 「 bOC UNIXV ANSI 機能の説明 fclose fclose ファイルをクローズする fdopen fdopen x ファイルティスクリプタとしてオープンする feof feof ファイルの終端を検出する fflush fflush ファイルバッフアのはきだしを行う fg ets fg ets ファイルから 1 文字読み取る X ファイルティスクリプタの拾得 fileno fileno ファイルのオープン fopen fopen 書式つきファイルへの出力 fp ri n tf fp ri ntf fputs ファイルへ 1 文字書き込む fp u ts ファイルからの読み取り f 「 ead fread ファイルからの書式つき読み取り fscanf fscanf 現在地の移動 fseek fseek 現在地の取得 ftell fte ファイルへの書き込み fw 「 ite fw 「 ite getc/fgetc getc/fgetc ファイルから 1 文字読み取る putc/fputc ファイルへ 1 文字書き込む putc/fputc 現在の位置をファイルの先頭に戻す 「 ewind rewind ユーザバッフアを指定する setbuf setbuf しているためだ。したがって , プログラミ ングを行うとき , 一般には高水準関数を使 用したほうがプログラムの互換性もよくな る。低水準関数は , ハードウェアに依存し た処理をするプログラムを作るときだけに 限ったほうがよいだろう。 ファイルポインタ ファイルポインタは , ファイルハンドル よりもより多くの情報が付加された構造体 として提供されている。参考のために Fig. 2 に MS-C と TurboC の構造体を示す ( 同じフ ーイ ~ ポイタの構造体と 0 、ても : MS ー C と TurboC て、は多少異なっているカ , これ を使用するプログラマとしては , この違い をとくに意識する必要はないだろう ) 。 ファイルポインタを基本にしている高水 準ファイル入出力関数て、は , たんにファイ ルハンドルを扱うだけて、はなく , それ以上 の情報をつねに管理するようになっている。 これらの関数て、は , 構造体のポインタとし てファイルポインタをつねに返してくるの て、 , 以後はこのポインタがファイルの ID と なり , すべての管理情報のもとになってい さらにファイルディスクリプタをファイ ルポインタのように扱うことがて、きる関数 , fdopen() 関数がある。これは , open() 関数 て、オープンされたファイルをファイルポイ ンタて、も扱えるようにするためのものて、 , 実際にはファイルディスクリプタをオープ ンしてファイルポインタを得る処理をほど ファイル八ンドルから ファイルポインタを得る方法 Fig. 2 日 LE 構造体へッダファイル ・ MS ー C の日 LE 構造体 #define FILE struct iobuf extern FILE { char *_pt 「 , cnt . char * base Char Char file , } NEAR CDECL iob ロ : int ・ Tu 「 boC の日 LE 構造体 control structure fO 「 St 「 eams * / / * Definition Of the typedef st 「 uct short unsigned Char unsigned Char short unsigned Char unsigned Cha 「 unsigned short / * fill/empty level Of buffer FiIe status flags FiIe desc 「 iptor Ungetc char if no buffer Buffer size Data transfer buffer Current active pointer / * Temporary file indicator Used fO 「 validity checking * / / * This is the FILE object level: flags : ho 旧 : bsize . * buffer , *curp , istemp , token , List int fh,• FI し E *fp; open("sample. doc" fh fdopen(fh, 78 CMAGAZINE 19 5

10. 月刊 C MAGAZINE 1990年5月号

とになります。 C 十十から取り込んだ C の表記の例とし て , たとえば引数がないことを強調したい ということて、あれば , 次のように void を書 きます。 / * no arguments * / f(void) また , 特定の引数が必要なことを強調し たいということて、あれば , 次のような形て、 表記されることになります。 / * one argument * / もちろん , 必ずしも名前 x を記述する必要 はありませんが , この x の表記をもっことに よって , 引数のチェックに大きな意義をも たせることて、きます。 て、すから , ある関数呼び出しが , 上記の ような宣言と一致しない引数による関数呼 び出しならばチェックが働き , 工ラーにな ります。また , 引数にポインタまたは構造 体を指定した場合てあっても , やはりチェ ックを得ることがてきます。この例て、は , ⅲ t に代入て、きる型の引数だけがエラーなし になります。 しかし , 実際には可変個の引数があり , それを表現て、きるような方法を提供するこ とも , 私たちにとって重要て、あると考えて いました。ひとつ以上の引数を宣言するこ とによって可変個の引数の関数に対処する ことがて、きるからてす。 f(char * p, … ) / * varying * / char * P は必ずそこに存在していなけれ ばならないことになります。しかし , 任意の引数をもってくることがて、きること を示しています。 printf や scanf 関数の引数を定義する際 には , この方法を使います。 ANSI C て、この printf 関数のファンクションプロトタイプ を書くことがて、きることは , たいへん重要 だと考えています。これに関して私たちは , f(int x) 60 CMAGAZINE 19 5 成功したと思います。 C 言語の追加機能として , この関数のプロ トタイプ宣言がもっとも重要なもののひと つだと思います。そして , 追加した際に さらにそこから次の段階への展開が見えて 型修飾子 ものて、あると確信します。 ての C プログラマにとって , 利益をもたらす そのため , 関数プロトタイプとは , とも , 重要な点て、す。 いるということがすて、に証明されているこ すべ ちろん私はここて、型修飾の話をしているわ 重要な変更事項てあると考えられます。も んどの場合 , 組み込みプログラムにとって とって有利て、あるとは考えませんが , ほと ります。必ずしも 100 % この変更が皆さんに プログラムにとってとくに重要なものがあ もうひとつ重要な追加として , 組み込み volatile const けて、すが , const char cc; / * can be ROMed * / て、す。 ば , そちらのほうがずっと簡単にすむわけ ースコードの中て、明確にすることがて、きれ て、すから , ROM の中に入れるデータをソ という問題が発生します。 イルにしてコンパイルしなければならない しかし , その場合 , ROM 用データを別ファ うことによって , その問題を解決しました。 ンパイラて、は , コンパイル時のフラグを使 たとえば旧バージョンの Whitesmiths の C コ ばならない状況が発生します。このとき , ときとして , データを ROM に入れなけれ の修飾子て、解決することがて、きます。 際に直面しうる問題の多くは , このふたっ 組み込みアプリケーションて、これらを書く というふたつの重要な型修飾子があります。 これて、 ROM の中に入れることがて、きま す。これはまた cc の内容をプログラムが変 更て、きない ( させない ) ことを意味します。 つまり , cc の内容を変更するような記述は 工ラーになるということて、す。もちろん C コ つまり , これは型と記憶クラスのちょう ばれるゆえんなのて、す。 りません。このことが , const が型修飾と呼 ンタがどこを指すのかを注意しなければな すると , ポインタがどこにあるのか , ポイ たとえば const をポインタと結びつけると なりません。 には , 必ずポインタのことも考えなければ す。そこて、 , const のような修飾を考える際 算やポインタを使ったメモリ参照がて、きま 機能がついています。ポインタを使った演 しかし C の場合には , ポインタと呼ばれる すことがて、きます。 に格納するのか , その名前によってのみ探 FORTRAN などの場合は , いったいどこ いへん大きな違いがあります。 に定義づけるのかというふたつの間に , た すればよいのかを知ることと , それをどこ へん微妙て、す。 C 言語の場合にはどこに格納 しかし , この分野に関して C 言語は , たい か定義しなければなりません。 ラスを通じて , const 変数をどこに格納する ていかなければならないからて、す。記憶ク は const のための新しい記憶クラスを整備し ど簡単な作業て、はありませんて、した。本来 は const を追加しましたが , これは , それほ がった動作をすることになります。私たち そうすると , 皆さんのプログラムはまち いのて、す ) 。 のて、す ( つまり完璧な不変定数が実現しにく 変更するようなコードも記述て、きてしまう どのちょっとした手段て、 const 変数の内容を は困難て、す。て、すからポインタを用いるな 変数へのアクセスをすべてチェックするの はありません。しかし , C コンパイラが const ROM の中になければならないというものて、 ンパイラにとっては , 必ずしもこの変数が