第67章 静的内部変数

 第65章で「静的」という言葉を説明しました。しかし、この説明は正確ではないのです。なぜなら、内部変数も静的にすることができるからです。今回はその方法について話します。


 今回の要点は以下の通りです。


 では、いってみましょう。


 先ず、静的変数の定義を確認しましょう。静的変数とは、「プログラムが実行される前(プログラムがメモリ上にロードされたときに)位置が決まっている変数」のことです。

 そして、静的でないデータの例として、引数と内部変数を挙げました。でも、内部変数は静的にすることができるのです。

 方法は簡単です。変数の型に static を加えるだけです。これだけで内部変数は静的変数になります。普通は static は先頭に書きますが、別にどこに書いても間違いではありません。

例)
void Func()
{
    static int a;
    cout << &a << endl;
}

 一方、静的でない内部変数のことを自動変数と呼びます。


 では、プログラムを作って、静的内部変数の動作を調べてみましょう。

 確認点を先に挙げておきます。グローバル変数は静的変数だったので、第9章で挙げたグローバル変数の特徴の中には、本来は静的変数全体における特徴があるはずです。それを踏まえて、以下のことを確かめてみます。

 では、やってみましょう。

プログラム実行結果例
長いので、別ウィンドウでご覧下さい
アドレスが常に一定かのチェック
&a = 0x0042A038
&b = 0x0065FD4C
in Sub2
&a = 0x0042A038
&b = 0x0065FCF8
&a = 0x0042A038
&b = 0x0065FD4C

初期化が1回しかされないかのチェック
a = 3
b = 3
a = 4
b = 3

0で初期化されるかのチェック
0,0,0,0
6684068,4366288,4366288,4242892

値が保証されるかのチェック
*pa = 9
*pb = 25637

 順に見ていきましょう。

 先ずは、「アドレスが常に一定か」のチェックです。

 自動変数 b のアドレスは AddressCheck_Sub2 内から呼ぶとアドレスが変わっていますが、静的変数 a のアドレスは常に 0x0042A038 で一定です。アドレスは常に一定のようです。これで、a はきちんと静的な変数になっていることが分かりましたね。

 そして、このアドレスを見ると、自動変数と静的変数では随分アドレスに差があることが分かります。このことも、自動変数と静的変数は別物であるということを示していそうですね。


 次は、「初期化が1回しかされないか」のチェックです。

 自動変数 b の値は、1回目も2回目も3でした。これは当たり前ですね。で、一方静的変数 a の値は、1回目は3でしたが、2回目は4になっています。2回目に関数を呼んだときには初期化が行われていないことが分かります。つまり、初期化は1回しか行われないわけです。


 次は、「0で初期化されるか」のチェックです。

 自動変数には全部変な値が入っています。値から見るとおそらく何らかのアドレスで、何かで使ったものがメモリ上にそのまま残っているようです。

 一方静的変数には全部0が入っています。このように、初期化を行わなかった場合は、静的変数は0で初期化されます


 最後は、「値が保証されるかのチェック」です。

 先ず、変数に9という値を入れ、それからその変数のアドレスを取得します。int*& というのは int* への参照です。ポインタもただの変数なので、もちろんポインタへの参照も作れます。このようにして、変数のアドレスを呼び出し側に返すわけです。

 で、次に HoldValueCheck_Sub2 関数を呼びます。ここでは関数を呼ぶということと、その中で大きな自動変数を作り0で埋めるということを行っています。この関数を呼ぶことで、メモリを大きく攪乱しているわけです。さらに、その後の cout でも攪乱されますね。

 で、値を表示します。自動変数の参照である *pb の値は、何か変な値になっています。自動変数 b の値は、関数を抜けると保証されないことがよく分かります。

 一方、静的変数の参照である *pa の値は、きちんと9のまま保存されています。これは偶然ではなく、もちろんこういう仕様になっています。このように、静的内部変数は関数を抜けても値が保証されます


 以上のことをまとめると、次のようになります。


 グローバル変数の特徴と思っていたものは、ほとんどが静的変数の特徴だったことが分かります。グローバル変数は無条件で静的変数になるわけです。


 今回はこれで終わりです。どうですか、分かりましたか?

 次回もまた変数についてのお話です。それでは、また次回まで。


第66章 インライン関数 | 第68章 寿命

Last update was done on 2000.7.28

この講座の著作権はロベールが保有しています