関数プロトタイプ宣言

関数プロトタイプ宣言は、関数定義における関数名、引数、戻り値の部分だけを行うものです。

// 関数プロトタイプ宣言
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

関連情報