第06問の答え

答え

main()の手前でサブルーチンを宣言するのが正解!
void PrintNumber(int n);
または、こう書いてもOK!
void PrintNumber(int);

解説

C言語では、手前で定義されたものしか使えません。今回のプログラムでは、main()からPrintNumber()を呼び出そうとしています。でも、この時点ではPrintNumber()が定義されていないので、コンパイルできなかったのです。

int main(void) {
  PrintNumber(123); /* ← この時点で定義されていない関数なので呼び出せない */

  ……
}

void PrintNumber(int n) { /* ← ここで定義されている */
  ……
}

次のように2つの関数の並び順を入れ替えれば、一応コンパイルできるようにはなります。

void PrintNumber(int n) {
  ……
}

int main(void) {
  PrintNumber(123);

  ……
}

だからといって、いつも並び順を気にしながらプログラムを考えるのは無理がありますね。

そこで、関数の宣言(プロトタイプ宣言)を使います。どこか別の場所で定義されている関数が、どのような形になっているのかをコンパイラに伝えるのです。

void PrintNumber(int n); /* ← プロトタイプ宣言 */

int main(void) {
  PrintNumber(123); /* ← 宣言された関数は呼び出せる */

  ……
}

こうしてPrintNumber()を宣言すれば、その定義(実体)はmain()関数のあとに書くことができます。または、別のソースファイルで定義するのでも構いません。

え、別のソースファイルって何のことですか?
それはね、大きなプログラムになると、ソースファイル1つじゃ作れないでしょう?
はい。そのときはファイルを分けると思います。
その場合でも、宣言があれば別のファイルで定義された関数を呼び出せるのよ。

C言語のこのような仕組みは、標準関数にも用いられているものです。例えばprintf()を呼び出したいときは、プログラムの冒頭で<stdio.h>をインクルードしますね。

#include <stdio.h>

<stdio.h>のなかには、標準入出力を扱う関数の宣言が収められています。printf()もその一つなので、冒頭にインクルードを書いておけば、プログラム中から呼び出せるようになるというわけです。

ここがポイント!
別の場所で定義された関数も、宣言すれば呼び出せる!

修正後のプログラム

main.c
#include <stdio.h>
#include <stdlib.h>

void PrintNumber(int n);

int main(void) {
  PrintNumber(123);

  return EXIT_SUCCESS;
}

void PrintNumber(int n) {
  printf("number = %d\n", n);
}
実行結果
number = 123