関数のプロトタイプ
昔のC 今のC
関数を作成して、それを呼び出すという基本的なことはできるようになりました
現時点で、すでに不便だと思っている人も沢山いると思いますが
関数を呼び出すには関数をそれよりも前に定義する必要がありました
一つ二つ程度の関数ではそれでもよいかもしれません
しかし、実際のプログラムでは数十、数百という関数を扱います
それを全てmain()関数よりも前に定義して、さらに関数から関数を呼び出すときの関係を把握しなければいけません
ハッキリ言って無理です。絶対いつかスパゲティー行きです
そこで関数のプロトタイプというものがあります
これは関数の宣言です
関数のプロトタイプ宣言では、戻り値、関数名、引数リストだけを指定します
関数のプロトタイプは、実は最近のC言語で実装されるようになったとっても素敵な技術らしいです
1989年にC言語が標準化され、そのときにプロトタイプが追加されたようです
関数のプロトタイプは、関数呼び出し時にコンパイラが型のチェックなどを行います
データ型の互換性などによるバグは非常に発見が困難とされるので重要です
このことは、今後引数と戻り値について詳しく解説しますので、そのときにわかると思います
関数のプロトタイプ宣言は、関数よりも前に次のように宣言します
戻り値の型 関数名(引数リスト);
#include <stdio.h>
void func(void);
int main() {
func();
return 0;
}
void func() {
printf("kitty on your lap");
}
これで、func()関数はmain()関数よりも後ろに存在しますが
場所に関係無く呼び出すことが可能になります
先ほども書きましたが、関数のプロトタイプは比較的新しい仕様です
実は、それ以前にも戻り値のデータ型をコンパイラに知らせるために前方宣言というものがありました
これは、プロトタイプの引数がない宣言です
戻り値の型 関数名();
過去の言語との互換性を考慮して、現代の新しいコンパイラにも実装されています
しかし、前章のプログラムのようなプロトタイプの無い関数や前方宣言は使われないです
すべてのC言語プログラムには必ず関数のプロトタイプを宣言して関数を扱うべきであるとされます
なぜこのようなことを話すかというと、引数で何も受け取らない関数の宣言に問題があります
プロトタイプの宣言のつもりで上のプログラムを以下のように書いたとします
#include <stdio.h>
void func(); /*前方宣言になってしまう*/
int main() {
func();
return 0;
}
void func() {
printf("kitty on your lap");
}
一見すると、問題のない関数のプロトタイプのように思えます
しかし、コンパイラは戻り値の型と関数名だけなので前方宣言と受け取るのです
コンパイルすると「プロトタイプ宣言のない関数の呼び出し」というような警告が出ます
これは非常に重要なことであり、知らなければ意外なところでエラーを出すかもしれません
引数で何も受け取らない関数の場合はvoidを指定しなければならないのです
上の二つのプログラムの大きな違いを理解してください
かなり過去に作られたC言語ソースをANSI C標準に移植するなどの場合には
もう少し詳しく調べる必要があるかもしれません