今回はstatic変数というものを紹介します。
サンプルプログラムを作りましょう。
※動かすのは待ってください。
<sample program 146-01>
#include <stdio.h> void Func(void); int main(void) { int i; for (i = 0; i < 5; i++) { Func(); } return 0; } void Func(void) { int value = 0; value++; printf("value = %d\n", value); } |
関数Funcを5回呼び出すプログラムです。
関数Funcでは、変数valueが宣言され初期値「0」が入っています。
変数valueの中見に1を加え、表示をして関数を終わります。
さて、どのような結果が表示されるでしょうか?
<実行結果>
value = 1 value = 1 value = 1 value = 1 value = 1 続行するには何かキーを押してください・・・
関数Func内で変数valueが宣言されています。
int value = 0; |
という書き方は、実は一部省略された書き方で、省略せずに書くと
auto int value = 0;
|
のようになります。
※「signed」も省略されていますが、そのままにしておきます。
この「auto」は「記憶クラス指定子」と言って、変数がメモリ上でどのように扱われるかを指定します。
「記憶クラス指定子」はいくつかありますが、「auto」は自動変数と言われるもので、通常省略されています。
自動変数は、関数が実行される際に変数としてのメモリ領域が確保され、関数が終了した時点で領域が解放されます。
上のプログラムで説明すると、
1回目の実行の時点で、初期値「0」が入り、1増えた後で表示され、 終了後に解放されます。
2回目に関数が実行される際に、再び変数としてのメモリ領域が確保されますが、また初期値「0」が入るため、同じように「1」が表示されて終わります。
1回目と2回目に確保される領域は同じである保証は無いため、初期値を入れなければ中身は不定です。
このように、(言い方は悪いですが)毎回「使い捨て」る変数だと考えてください。
では、ここからstaticというキーワードを使って、プログラムを変更してみましょう。
関数Func内のローカル変数valueの前に「static」というキーワードを付けるだけでどう変わるのか見てください。
<sample program 146-02>
#include <stdio.h>
void Func(void);
int main(void)
{
int i;
for (i = 0; i < 5; i++) {
Func();
}
return 0;
}
void Func(void)
{
static int value = 0;
value++;
printf("value = %d\n", value);
}
|
<実行結果>
value = 1 value = 2 value = 3 value = 4 value = 5 続行するには何かキーを押してください・・・
変数valueの数が1ずつ増えています。
staticを付けることで何が起こったのか説明します。
まず、staticが付いたとは言え、変数valueは関数Func内で宣言されていますので、関数Func内でしか使用出来ません。
ローカル変数、というところは変わっていないということですね。
しかし、自動変数では無くなっています。
staticとは「静的」という意味であり、コンピュータ的な説明をすると、「プログラムが実行される前にあらかじめ何かしておく」というような意味になります。
対義語は、dynamicで「動的」という意味であり、「プログラムの実行中に何かする」というような意味でとらえておいてください。
※C言語には、dynamicというキーワードはありません。
staticを付けることにより、変数valueはあらかじめ用意され、関数の呼び出し前から存在します。
また、関数が終了した後も残っています。
さらに、初期値は設定しなくても「0」になります。
試しに、
static int value = 0; |
の
= 0 |
を外して動かしてみてください。
<sample program 146-03>
#include <stdio.h>
void Func(void);
int main(void)
{
int i;
for (i = 0; i < 5; i++) {
Func();
}
return 0;
}
void Func(void)
{
static int value;
value++;
printf("value = %d\n", value);
}
|
<実行結果>
value = 1 value = 2 value = 3 value = 4 value = 5 続行するには何かキーを押してください・・・
実行結果は変わりません。
少し細かく説明しましょう。
プログラムが実行される前にstatic変数valueが用意され、初期値「0」が設定されます。
関数Funcが呼び出され、変数valueに1加算し、表示します。
関数が終わった後も、変数valueは残っており「1」を保持しています。
2回目に関数Funcが呼び出され、変数valueに1加算し、表示します。
関数が終わった後も、変数valueは残っており「2」を保持しています。
・
・
・
このように、関数内で宣言された変数の値を残しておきたい時にstatic変数を使います。
例えば上記のプログラムだと、この関数が何回呼び出されたかが分かりますね。
※自動変数の場合、初期値は不定です。
ついでに「記憶クラス指定子」をもう1つ紹介します。
register
というキーワードです。
register int value; |
と書いた場合、変数valueはCPU内のレジスタ(記憶場所)に確保される(かも知れない)という意味です。
確保されるかどうかは状況次第らしいです・・・使ったことが無いので正直分かりません。
何のためにあるのかというと、プログラムやデータはメモリに配置され、必要なものがCPUに取り込まれて実行されます。
CPUからメモリにアクセスするよりも、CPU内部のレジスタにアクセスした方が高速です。
そこで、頻繁にアクセスする必要のある変数をレジスタ内に確保することによって、処理速度の向上が見込めます。
ただ、レジスタは容量が小さいため、何でもかんでもという訳にはいきません。
速度が向上するかどうかは環境次第ということでしょう・・・
もう1つ
extern
というキーワードもあるのですが、こちらは「ファイル分割」のところで説明します。