関数プロトタイプ宣言
関数プロトタイプ宣言は、関数定義における関数名、引数、戻り値の部分だけを行うものです。
// 関数プロトタイプ宣言 int32_t foo(int32_t args1, double args2);
実務的な用途では、関数プロトタイプ宣言は、関数定義より上で行われます。
// 関数プロトタイプ宣言 int32_t foo(int32_t args1, double args2); // 関数定義 int32_t foo(int32_t args1, double args2) { // 処理 }
分割コンパイルできるように構成されたプログラムでは、関数プロトタイプ宣言は、ヘッダに配置されます。
mylib.h
// 関数プロトタイプ宣言 int32_t foo(int32_t args1, double args2); <pre> <b>mylib.c</b> <pre> // 関数定義 int32_t foo(int32_t args1, double args2) { // 処理 }
そもそも何のための関数プロトタイプ宣言なの?
そもそも何のための関数プロトタイプ宣言なのですか?
C言語の仕様やコンパイル技術について、少し知る必要があります。
C言語は、関数定義より後に、関数呼び出しがあった場合には、関数を見つけることができません。
int main (void) { // 見つからない foo(1, 2.5); } // 関数定義 int32_t foo(int32_t args1, double args2) { // 処理 }
関数プロトタイプ宣言は、これを解決することができます。
int32_t foo(int32_t args1, double args2); int main (void) { // 見つかる foo(1, 2.5); } // 関数定義 int32_t foo(int32_t args1, double args2) { // 処理 }
さらに別のソースファイルから、この関数を呼び出したいとします。そうした場合に、処理の実体である関数定義ではなく、関数の仕様、つまり名前と引数と戻り値だけをヘッダで、公開します。
mylib.h
int32_t foo(int32_t args1, double args2);
mylib.c
#include "mylib.h" // 関数定義 int32_t foo(int32_t args1, double args2) { // 処理 }
myapp.c
#include "mylib.h" int main (void) { // 見つかる foo(1, 2.5); }
これだけで、他のソースファイル(ここではmyapp.c)がコンパイルできます。もちろん、mylib.cもコンパイルできます。つまり、コンパイルするためには、関数の実体は必要ではなく、関数の仕様がわかればよいということです。
# 分割コンパイル gcc -c -o myapp.o myapp.c gcc -c -o mylib.o mylib.c
そして、リンクのタイミングで、関数の実体を結びつけます。
# リンクして実行ファイル生成 gcc -o myapp myapp.o mylib.o