« HDD ハードディスク ドライブ セクター 不良 | HOME | C言語:static 関数への使用 »

C言語:extern

C言語:extern
「MW web studio(http://homepage1.nifty.com/aok2/)」

全ファイル中のどこかに定義してある、という意味です。複数ファイル構成で分割コンパイルする場合に必要で、一般的には共通ヘッダファイルに記述します。

ファイル1個プログラムではあまり使い道がありません。しかし、厳密にはファイル1個でもライブラリ内の関数や変数を参照する場合にextern宣言が必要です。ライブラリはコンパイル済みCファイル(の集合体)と考えるためです。

2つの使い方があります。
 1. 関数(のプロトタイプ宣言)
 2. グローバル変数(他ファイル内に定義されている)


1. 関数のプロトタイプ宣言
関数のプロトタイプ宣言にexternを付ける付けないは、あまり問題になりません。

----------- a.c -----------
int func_A( int n ); /* OK */
extern int func_A( int n ); /* OK */

int func_A( int n )
{
}


----------- b.c -----------
int func_A( int n ); /* OK */
extern int func_A( int n ); /* OK */

int func_C( int n )
{
/* a.c の func_A を呼んでいる */
func_A( n );
}

extern は、「全ファイル中のどれかに定義されている」ですから、 extern int func_A(int n); は、a.c でも、b.c でも同じように宣言できます。
staticではない関数は、自動的に外部から見えると解釈されます。なので関数の場合は、extern を省略できます。省略しないほうがいいですが。
戻り値が int型の関数は、プロトタイプ宣言すら省略できますが、なるべくプロトタイプ宣言をしましょう。

2. 変数
2.1 正しい使い方
まずは正しい使い方です。 a.c 内で定義された int a; を b.c 内で使っています。

----------- a.c -----------
int a;

func_A()
{
a = 1;
}
----------- b.c -----------
extern int a;

func_B()
{
a = 2;
}

2.2 コンパイルエラー
この例では、a = 2; の a は、b.c内では定義されていないよ!とコンパイルエラーになります。

----------- b.c -----------
/* extern int a; */

func_B()
{
a = 2;
}

2.3 リンクエラー(1)
----------- b.c -----------
/*extern*/ int a;

func_B()
{
a = 2;
}

コンパイルはOKです。しかしリンクで、変数 a が、a.c、b.c 2箇所で定義されています?とリンクエラーになります。

一つのプログラム内では、同じ名前のグローバル変数は使えません。(グローバル変数とは、関数の外で定義した変数)

似たような例を紹介しますが、一つの関数内では、同じ名前のローカル変数は使えません。(ローカル変数とは、関数の中で定義した変数)

func_A()
{
int x;
int x; /* エラー */
}

2.4 リンクエラー(2)
----------- a.c -----------
/* int a; を定義しない */

----------- b.c -----------
extern int a; /* どこかにあるはず */

func_B()
{
a = 2;
}

b.c のコンパイルはOKです。b.c の変数a の扱いは「別ファイルにあるはず」と、変数a に関する問題を先送りにします。しかしリンクのとき、全ファイルを見渡しても変数a はどこにもない、とリンクエラーになります。
「MW web studio(http://homepage1.nifty.com/aok2/)」


 

ハワイ旅行| サトピの子連れグアム旅行記| グアム旅行の情報サイト| ガーデニング|

Copyright (C) 2009 Anne Corporation. All Rights Reserved.