プロトタイプ宣言

これまで、「呼び出される関数」は、必ず「呼び出す関数」の上で定義していました。
これは、コンパイラがソースを上から読んでいくためにそうするといいましたね。
しかし、これではソースが長くなってくると、複雑になってきます。
今回は、関数の定義の順番を気にしない方法を説明します。

コンパイラは関数呼び出しの文を見つけると、
「その関数が存在するか」「引数の数と型が一致しているか」等を調べます。
逆に関数の定義をしていなくても、コンパイラに関数の情報―すなわち、
「こういった型で、このような引数を持つ関数がある」と知らせれば、
関数呼び出しの文は成立します。

とまあ、言葉だけではどうも複雑になっていくので実際にソースを見てみましょう。
それではゆっくりとご覧ください。

01:#include <stdio.h>
02:
03:void MyFunction();
04:
05:int main()
06:{
07:  MyFunction();
08:  return 0;
09:}
10:
11:void MyFunctiono()
12:{
13:  printf("MyFunction関数の処理です\n";)
14:}

3行目になにやら、関数の定義のようでもあり、呼び出しのようでもあるものがありますね。
これは「void型のMyFunctionという引数を持たない関数が存在する」と宣言しています。
よって、まだMyFunction関数が定義されていない7行目でMyFunction関数を呼び出せます。

このように、関数の処理を定義する前に、関数の情報を定義することを、
関数のプロトタイプ宣言といいます。
関数のプロトタイプ宣言さえすれば、もう関数の定義の順番を気にする必要はありません。

それでは、下に関数のプロトタイプ宣言の仕方を示します。

データ型 関数名(引数のデータ型);

最後のセミコロン(;)は忘れやすいので注意してください。
また、「引数」ではなく「引数のデータ型」となっているのにも注目してください。
これはどういうことかというのは下で説明します。


int f(int);

int main()
{
  int y;
  y=f(4);
  return 0;
}

int f(int x)
{
  return 3*x+7;
}

関数fの定義では (int x) となっているのに、
プロトタイプ宣言では (int) となっているのに、気付いてもらえたでしょうか?
コンパイラが必要とするのは仮引数の数とデータ型なので名前は必要ないというわけです。
(プロトタイプ宣言で仮引数の名前まで記述してもまったく問題はありませんが....)