プリプロセッサーは,コンパイルに先だって,ソースファイルを変更している2.gcc ではいろいろな処理が行われるが,プリプロセッサーの動作が一 番最初に実施される.そこで,諸君が書いたC言語のプログラムを変更しているのである. preprocessor(pre:あらかじめ,processor:処理するもの)という名前からも,そのことが よくわかる.
プリプロセッサーができることは,教科書のp.283の表に示されている.いろいろな機能 があるが,本講義で使うのは -4pt
#コマンド パラメーターリスト
このプリプロセッサーの書き方には,以下の約束がある.
プログラマーが自分でヘッダーファイルを書くことがある.例えば,大規模なプ ログラムを作成する場合,ファイルは1つではなく,いろいろな部分を別々のファイルに 書いて,それをあとであわせて,1つのプログラムにする(分割コンパイル).その場合 には,共有する構造体や大域変数を1つのファイルにして,myfile.hというようなファ イルを作り,それぞれのソースプログラムでインクルードする.このようにすると,同じ 文をそれぞれのファイルに記述する必要が無くなり,タイピングが楽になるとともに,ミ スが減る.ここでの学習では,分割コンパイルをするほどのプログラムを書くことはない.将来,比 較的大きなプログラムを書くときに,勉強すればよいだろう.
#includeの動作の理解のために,へんなプログラム例を示す.Hello World
!!を出力するおなじみのプログラムである.
1 #include <stdio.h> 2 #include "hoge" 3 return 0; 4 }
これをコンパイルして,実行ファイルを作るためには,以下のファイル(hoge)が必
要である.当然,このファイルはソースプログラムのインクルード文で取り込まれる.
1 int main(void){ 2 printf("Hello World !!\n");
実行の結果,#includeにより,そこの行が指定のファイルに置き換わっているのが 理解できるはずである.使い方によっては,便利そうであることが理解できればよい.こ の行の置き換えはコンパイルの前に行われることに注意が必要である.
less /usr/include/stdio.h
その中をみると,関数のプロトタイプ宣言等がごちゃごちゃ書かれているのが分かるだろ う.これが,諸君のプログラムの最初の方に追加されるのである.これで, printf()などの関数が使えるようになるのである.
単純な文字列置換をオブジェクト形式マクロと言う.これは,次のように書く
#define hogehoge fugafuga
置き換え前の文字列--ここではhogehoge--はすべて大文字で記述する習慣 となっている.別に小文字でも問題なく動作するが,ほとんどのプログラマーは大文字を 使う.その方が,プログラムがわかり易いからである.
#define NSTEPS 361
リスト3のプログラムは,三角関数の数表を出力する.0〜2ラジ アンを360等分して,関数の値を計算,そして出力している.例えば,500等分の値を出力 したければ,#define NSTEPS 501とする.文字列置換を使えば,プログラムの変更 が容易であることがわかる.
このプログラムの31行目に,M_PIというわけの分からない変数らしきものがある. 実は,これも文字列置換の対象である.ヘッダーファイルmath.hの中に,
# define M_PI 3.14159265358979323846 /* pi */
less /usr/include/math.h
このプログラムは,数学関数--こでは三角関数--を使っている.そのため,ヘッダーファ イルmath.hをインクルードしている.さらに,これをコンパイルするためには,
gcc -o keisan sankaku.c -lm
1 #include <stdio.h> 2 #include <math.h> 3 4 #define NSTEPS 361 5 6 void cal_function(double x[], double s[], double c[], double t[]); 7 8 /* ==================================================================== */ 9 /* メイン関数 */ 10 /* ==================================================================== */ 11 int main(void){ 12 double x[NSTEPS], s[NSTEPS], c[NSTEPS], t[NSTEPS]; 13 int i; 14 15 cal_function(x, s, c, t); 16 17 for(i=0; i<NSTEPS; i++){ 18 printf("%f\t%f\t%f\t%f\n",x[i], s[i], c[i], t[i]); 19 } 20 21 return 0; 22 } 23 24 /* ==================================================================== */ 25 /* 関数計算 */ 26 /* ==================================================================== */ 27 void cal_function(double x[], double s[], double c[], double t[]){ 28 int i; 29 30 for(i=0; i<NSTEPS; i++){ 31 x[i]=(double)i/NSTEPS*2.0*M_PI; 32 s[i]=sin(x[i]); 33 c[i]=cos(x[i]); 34 t[i]=tan(x[i]); 35 } 36 37 }