グローバル変数

グローバル変数


サイト全体の目次

稿


稿

グローバル変数

このセクションのソース

変数のスコープについては以前説明したとおりですが、少し補足しておきます。

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ int x;
/*04*/ 
/*05*/ main()
/*06*/ {
/*07*/   void Func(void);
/*08*/ 
/*09*/   x = 10;
/*10*/   Func();
/*11*/ 
/*12*/   return 0;
/*13*/ }
/*14*/ 
/*15*/ void Func(void)
/*16*/ {
/*17*/   printf("x=%d\n", x);
/*18*/ }

(untitled)

このリストのように、変数は関数の外側で宣言することもできます。この場合、プログラム中のどこからでもこの変数にアクセスできます。このような変数をグローバル変数といいます。これに対し、各関数内で宣言された変数は局所変数ローカル変数といいます。

こうすると一見便利なように見えますが、その変数がどこで使われているのかはっきりしなくなり、時には同じ変数名の変数を関数内で宣言してしまって思わぬ結果になるなどの不都合もあります。この例の場合なら、Func 関数で表示させる値は引数で与えるなどして独立性を保つほうがよいでしょう。

記憶クラス

このセクションのソース

次は記憶クラスというものについてです。

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   int x;
/*06*/ 
/*07*/   for(x = 0; x < 10; x++){
/*08*/     int y = 1;
/*09*/ 
/*10*/     printf("%d\n", y);
/*11*/     y++;
/*12*/   }
/*13*/ 
/*14*/   return 0;
/*15*/ }

(untitled)

まずこの例を実行してみてください。for 文では、毎回 y がインクリメントされて、1から10まで順に表示されることを期待したいのですが、実際には「1」が10回表示されるだけとなります。なぜでしょう?これは、for 文の各ループが終了するたびに、そのブロックから1度抜けてしまっているからです。概念としては、for 文以下のブロックが、for 文で指定された回数だけ並んでいる、という感じでしょうか。ただし、for 文で使われている変数 x は各ブロックから見てグローバルということになります。つまり、上の例なら次のような感じでしょうか。

x = 0;
{
    int y = 1;
    printf("%d\n", y);
    y++;
}

x = 1;
{
    int y = 1;
    printf("%d\n", y);
    y++;
}

x = 2;
{
    int y = 1;
    printf("%d\n", y);
    y++;
}

:
:

この現象は、これまで使ってきた変数の記憶クラスと呼ばれるものがauto型であるために起きます。このタイプの変数は上の例のように、変数が宣言されたそのブロックを抜けると、その変数は完全に消去されてしまうのです。

これに対して、記憶クラスがstaticというタイプの変数は一度ブロックから抜け出しても変数の値が保持されます。ですから、再び同じブロックを実行した場合、前に保持されていた値をそのまま使うことになります。まずは、宣言のしかたからまとめてみましょう。

1: int x;
2: auto int x;
3: static int x;    /* [記憶型] [変数型] [変数名];    として宣言 */

まず、1番目は今までどおりと同じ宣言のし方です。1番目のように宣言された変数は、自動的に「auto」変数とみなされます。これに対し、2番目は auto 変数であることを明示しています。しかし、1番目と2番目とでは何の違いも無いので、普通は今までどおり1番のように宣言することのほうが多いでしょう。そして3番目は、その変数を「static」として宣言しています。

さて、auto 型と static 型ではメモリ上の取られ方が違います。auto 型は上で説明したとおり、宣言したブロックを抜けるとメモリ上から消去されてしまいます。これに対し、static 型で宣言された変数はそのブロックを抜けても、同じメモリ上に居座りつづけ、同じブロックが再び実行された場合はそれが使われます。(これらの型を記憶クラスと言います。)

では実際に例を見て見ましょう。

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   int x;
/*06*/ 
/*07*/   for(x = 0; x < 10; x++){
/*08*/     static int y = 1;
/*09*/ 
/*10*/     printf("%d\n", y);
/*11*/     y++;
/*12*/   }
/*13*/ 
/*14*/   return 0;
/*15*/ }

static で宣言された変数は、そのブロックが使われる1番最初にだけ初期化が行われるのです(これが重要)。ですから、この例では1から10まできちんと表示されます。また、このようにすると処理の流れは次のようになります。
1回目のループ
    変数 y が宣言され「1」に初期化。
    (y を使った操作など。)
1回目のループ終了

2回目のループ
    変数 y の値は、1回目のループ終了時のまま。
    (y を使った操作など。)
2回目のループ終了
            :
            :

この時、宣言と同時に初期化するのがコツです。というのも、もし
static int x;

x = 1;

とやってしまうと、毎回 x に「1」が「代入」されてしまうので、結果としては auto 変数と同じ結果になってしまうのです。

static 変数を使うときの注意として、次のような疑問が湧くと思います。「static 変数はそのブロックを抜けても値が保持されるんでしょ?それなら、そのブロックの外でもその変数が使えるんじゃない?」これは大きな間違えです。変数の有効範囲はあくまでも上で書いたとおりなので、その変数が宣言されたブロックの外では有効ではありません。

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   int i;
/*06*/ 
/*07*/   for(i = 0; i < 10; i++){
/*08*/     static int x = 1;
/*09*/ 
/*10*/     x++;
/*11*/   }
/*12*/   printf("%d\n", x);    /* x を参照できない */
/*13*/ 
/*14*/   return 0;
/*15*/ }

関数と static 変数

このセクションのソース

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   void Func(void);
/*06*/   int i;
/*07*/ 
/*08*/   for(i = 0; i < 10; i++)
/*09*/     Func();
/*10*/ 
/*11*/   return 0;
/*12*/ }
/*13*/ 
/*14*/ void Func(void)
/*15*/ {
/*16*/   static int x = 1;    /* int x;(auto 型)でも試してみてください */
/*17*/ 
/*18*/   printf("%d\n", x);
/*19*/   x++;
/*20*/ }

(untitled)

さて、static に関する性質は関数の呼び出しについても同じことが言えます。必要に応じて使い分けてください。(ただし、static はプログラムの終了までメモリ上に居座るので、メモリを無駄に占拠する可能性があります。)


読み込み中・・・
10秒待っても表示が変わらない場合、次の理由が考えられます。
・Javascript が無効になっています。
・検索エンジンのキャッシュを見ています。
サイトホームへ / 上位ページへ / ページトップへ / PAROFトレンドショッピングへ
Copyright (C) 2010 totobon all right reserved.