プログラム中に同じオブジェクト名や関数名で複数の宣言があるとき,それらが同一のオブジェクト,或いは関数として参照されることをリンケージあるいは結合と言います。
■結合(リンケージ,Linkage)[C99, 6.2.2]
そのソースファイル内で同一のオブジェクト,或いは関数として参照。
プログラムが複数のソースファイルから構成される場合,それらすべてのソースファイルにおいて同一のオブジェクト,或いは関数として参照。
リンケージは,有効範囲と記憶域クラスで決まります。
記憶域クラス | データ | 有効範囲 | リンケージ |
指定なし | オブジェクト | ファイル・スコープ | 外部結合 |
ブロック・スコープ | なし | ||
関数 | ファイル・スコープ | extern と同じ。 | |
ブロック・スコープ | |||
static | オブジェクト | ファイル・スコープ | 内部結合 |
ブロック・スコープ | なし | ||
関数 | ファイル・スコープ | 内部結合 | |
extern | オブジェクト, 関数 | ファイル・スコープ | 可視な宣言済みの同一識別子がリンケージをもつ場合,それと同じリンケージを持たせる。可視な宣言済みの同一識別子がない,或いは存在してもそれがリンケージを持たない場合,外部結合を持つこととなる。 |
ブロック・スコープ |
* 「ファイル・スコープ」,「ブロック・スコープ」,「可視」については「16.1. 変数の有効範囲」を参照。 |
extern
を付さないブロック・スコープのオブジェクトは,リンケージなし(無結合,No Linkage)となります。[C99, 6.2.2, 6]
関数に対しては static
はファイル・スコープを持つ場合にのみ許される。
■リンケージがある場合の初期化ルール
sizeof
演算子以外に使用する場合,外部定義が必要。しかも,それは一つに限る。[C99, 6.9, 3&5]
/* Example 16.3 */ char c = 'A'; static double pi = 3.14; int main(void) { extern double x; char c; static long l; }
最初の char
型変数 c
はファイル・スコープを持ち,記憶域クラスの指定がありません。したがって,外部結合を持ちます。double
型変数 pi
はファイル・スコープを持ち,記憶域クラスには static
を指定しています。したがって,内部結合をもちます。外部結合はないので,宣言されているソースファイルのみのリンケージとなります。変数 x
は,宣言済みの同一変数がないので外部結合を持ちます。これには外部定義が必要です。また,ブロック・スコープを持つので初期化はできません。main
関数内の変数 c
は,3行目で宣言している変数 c
を隠すので,それとは異なる無結合変数として認識されます。同一と認識させるには,変数の宣言を削除するか,3行目の変数 c
がリンケージを持っているので extern
を付せば良いです。変数 l
は記憶域クラスに static
を付していますが,ブロック・スコープをもつため,リンケージをもちません。