授業/C言語基礎/コンパイルとリンク のバックアップ差分(No.2)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
*関数の宣言 [#z34026d5]
*コンパイル [#h2c785d0]

関数を使うには、呼び出すよりも前に、関数を''宣言''する必要があります。
これを関数の''プロトタイプ宣言''といいます。
ある言語で書かれたものを別の言語で書かれたものに変換(翻訳)することを''コンパイル''といいます。

関数は、次のように宣言します。
この授業では、C言語で書かれたプログラムをコンピューターが実行可能な機械語のプログラムにコンパイルしています。

**コンパイラー [#rba646af]

コンパイルするソフトウェアのことを''コンパイラー''といいます。

この授業では、''gcc''というコンパイラーを使用しています。

gccを用いてCプログラムのファイル名だけを指定してコンパイルすると、 ''a.out'' という名前の実行形式のファイルが出力されます。
#geshi(sh){{
luna% gcc hello.c
}}

**実行形式のファイル名を指定する [#qbe406af]

gccに ''-o'' オプションを指定すると、出力される実行形式のファイルの名前を指定することができます。
#geshi(sh){{
luna% gcc -o hello hello.c
}}



**演習1 [#sd56e6f9]
画面にHello World!と出力するプログラムhello.cを作成し、実行形式のファイル名をhelloにしてコンパイルせよ。


*他のファイルに定義された関数を使う(外部結合) [#ic383494]

これまでは、すべてのプログラムが一つのファイルに記述されていました。

大規模なソフトウェアになると、機能などのまとまりごとにモジュールに分割してプログラムを作成します。
すると、他のファイルに定義されている関数を呼び出すことがあります。

このようなとき、記憶域指定子として ''extern'' をつけてプロトタイプ宣言を記述します。
#geshi(c){{
戻り値の型 関数の名前(引数1の型 引数1の名前, 引数2の型 引数2の名前, ...);
extern 戻り値の型 関数名(引数1の型 引数1の名前, 引数2の型 引数2の名前, ...);
}}

ただし、呼び出すよりも前に関数を「定義」しているときは、関数の「宣言」を省略できます。
実は、これまでは、関数を呼び出すよりも前に定義して、関数の宣言を省略していました。
例えば、次のようなプログラムがファイル add.c に定義されているとします(プログラム1a)。
#geshi(c){{
/*
 *  add.c
 */
double add(double x, double y) {
  return x + y;
}
}}

たとえば、プログラム1で作成したadd関数を呼び出すよりも後に定義する場合は、次のように宣言します(プログラム5)。
これを、main.c というファイルのmain関数から呼び出すときには、呼び出す前にexternを付けたプロトタイプ宣言が必要になります(プログラム1b)。
#geshi(c){{
/*
 *  main.c
 */
#include <stdio.h>

int add(int x1, int x2);
extern double add(double x, double y);


int main(void) {
  int i = 1, j = 2, k;
  
  k = add(i, j);
  printf("%d\n", k);
  
  double x = 1.0, y = 2.0;
  double z = add(x, y);
  printf("%f\n", z);
  return 0;
}
}}


int add(int x1, int x2) {
  int y = x1 + x2;  
  return y;
}
複数のファイルに分けて記述されたプログラムをコンパイルするときは、すべてのプログラムを同時に指定します。
#geshi(sh){{
luna% gcc add.c main.c
}}

これらのプログラムは、単体では実行可能なファイルにコンパイルすることができません。
#geshi(sh){{
luna% gcc add.c
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld はステータス 1 で終了しました
luna% gcc main.c
/tmp/ccUSNIu9.o: In function `main':
main.c:(.text+0x3f): undefined reference to `add'
collect2: ld はステータス 1 で終了しました
}}

**演習5 [#ae2b7a3b]

プログラム1をプログラム5に変更し、実行結果を確認せよ。

**演習2 [#o7ee209c]
プログラム1a, 1bを作成し、実行結果を確認せよ。


*オブジェクト・ファイル [#xbba462f]

大規模なプログラムになると、コンパイルにかなりの時間がかかります。
一部だけに誤りがあったり、一部だけを変更したときに、すべてのプログラムをコンパイルしなおすのは、大変です。

そこで、ファイルごとにCプログラムを中間ファイルにコンパイルします。
この中間ファイルのことを''オブジェクト・ファイル''といいます。

Cプログラムをオジェクト・ファイルにコンパイルするには、gccに ''-c'' オプションを指定します。
#geshi(sh){{
luna% gcc -o add.c
luna% gcc -o main.c
}}

オブジェクト・ファイルの名前は、Cプログラム(ソース・ファイル)の名前の拡張子を ''.o'' に変えたものになります。

**演習3 [#xac1421a]
プログラム1a, 1bについて、それぞれオブジェクト・ファイルにコンパイルせよ。


*リンク [#o84f9750]

ファイルごとにオブジェクト・ファイル作成し、必要なオブジェクト・ファイルがすべて揃ったら、オブジェクト・ファイルを結合し、実行可能なファイルを作成します。
これを''リンク''といいます。

オブジェクト・ファイルをリンクして実行可能なファイルを作成するのにもgccを使います。
#geshi(sh){{
luna% gcc add.o main.o
}}


**演習4 [#y85f1933]
演習3で作成したオブジェクト・ファイルをリンクし、実行可能なファイルを作成せよ。

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS