C.外部変数参照 extern
外部変数とは、全ての関数から参照できる変数です。関数の外側で記憶クラスを省略して宣言すると変数の領域が確保されます。
この外部変数は同一のソースファイル内の宣言している行以降であればそのまま参照できます。ただし、同じソースファイル内でも宣言している行より前で参照したり、他のソースファイルから参照する場合にはそのままでは参照できません。ここで外部変数参照を使います。
extern を使って宣言された変数はメモリ内に領域が確保されません。どこかで宣言されている外部変数を参照できるようにするだけなのです。

通用範囲記憶領域
グローバル変数静的領域

[ 1 ] 外部変数を宣言すると、同一ソースファイルの宣言した行以降で自由に参照できます。
外部変数の通用範囲
[ 2 ] ソースの中程で外部変数を宣言した場合、宣言した行以降は自由に参照できますが、宣言よりも前で参照する場合は extern 宣言が必要です。
途中で宣言した外部変数の通用範囲
[ 3 ] 複数のソースファイルに分割してプログラムを作成する場合、宣言を含まないファイルで参照する時には extern 宣言が必要です。
他のファイルの外部変数の参照
ソースファイルB の例のようにファイルの先頭で外部変数的に extern すると、それ以降のすべての関数から max が参照できることになります。これは便利な反面、max がどこで使われているかを把握しづらくなりバグの原因になりやすくなります。

[ 4 ] 外部変数を別のファイル内で宣言しておき、参照する関数ごとに extern するのが一番よいスタイルです。そうすれば、extern を行った関数内だけで max が参照できるようになり他の関数からは参照できません。
extern の良い使い方

D.静的変数 static


静的変数は、静的領域に確保される変数です。関数内でも外でも宣言できますが、次のように通用範囲が変わってきます。
関数外で宣言された場合は、通用範囲はそのソースファイル内だけで他のソースファイルからは参照できません。これによってソースファイル間での変数名の衝突を防止できます。
関数内で宣言された場合は、通用範囲は自動変数と同じでその関数内だけです。しかし、自動変数と違い関数の外に制御が移った場合でも内容を保持しています。つまり、もう一度その関数が実行されたときには前の値が保存されていることになります。

通用範囲記憶領域
グローバル変数
ローカル変数
静的領域

静的変数 static

5.記憶クラスによる初期化の違い


動的領域と静的領域は初期化のされ方が違います。動的領域は関数が呼ばれる度にスタック領域に領域が確保されます。従って、関数が呼ばれる度に初期化が行われます。静的変数はコンパイル時にデータ領域に領域が確保されて、プログラムが実行されたときにはメモりに値が確保されるだけです。従って、初期化はコンパイル時に一度だけ行われます。

記憶クラス記憶領域初期化のされ方初期化をしなかった場合
自動変数
レジスタ変数
動的領域実行時に関数の呼び出しごと不定
外部変数
静的変数
静的領域コンパイル時に一度だけ自動的に0に初期化

6.記憶クラスの上手な使い分け


変数をある意味を持った定数的な使い方をしたいときがあります。このような場合は静的な外部変数として確保するのが良いでしょう。さらに、const をつけて宣言すると初期化された変数の値を変更できなくなります。つまり、誤って値を変えてしまうこともなくなります。

const double pai = 3.14; /* πを宣言 */

void func (void) {
 pai = 5.0; /* コンパイル時にエラーとなる */
}

配列を使うとき、サイズが大きい場合で一度だけ初期化すれば良いような場合は静的変数で確保すると良いでしょう。初期化にかかる時間が短縮されて実行速度が向上します。
 [ 例 ] 静的な場合と動的な場合の初期化速度の差の例  ex8-2.cGet! ソースファイル
  結果例 動的 = 2.69秒 静的 = 1.65秒


○ソースファイルのダウンロード○
この章に使った例のソースファイルを1つにまとめて圧縮してあります。
 【中に含まれているソースファイル】
  ex8-1.c ex8-2.c

ソースファイルのダウンロードexample08.lzh (2,296 Bytes)


Jump to Phase #08-1Phase #08-1: 変数の記憶クラス(1) へ
Phase #09-1: ポインタ(1) へJump to Phase #09-1

△戻る
▲トップに戻る