変数の寿命とスコープ


次のプログラムを見て下さい。

ソースコード

源文件
  1|/* span01.c */                                                              
  2|
  3|#include <stdio.h>
  4|
  5|int add(int);
  6|
  7|int main(void)
  8|{
  9|  int sum;
 10|
 11|  sum = add(10);
 12|  printf("sum = %d\n", sum);
 13|
 14|  sum = add(20);
 15|  printf("sum = %d\n", sum);
 16|
 17|  sum = add(100);
 18|  printf("sum = %d\n", sum);
 19|
 20|  return 0;
 21|}
 22|
 23|int add(int x)
 24|{
 25|  int gokei = 0;                                                            
 26|  gokei += x;
 27|  return gokei;
 28|}

実行結果

sum = 10
sum = 20
sum = 100

add関数は、呼び出し元からもらった値をgokeiにどんどん加えていくつもりで作った関数です。例えば

  • sum = add(10);
    とすれば、 sum の値は10になり、次に
  • sum = add(20);
    とすれば、 sum の値は30になり、次に
  • sum = add(100);
    とすれば、sum の値は130になることを期待して作ったわけですが、結果は全然違います。

どうしたことでしょうか。実は、関数内で宣言した変数には寿命があるのです。関数が制御を戻すたびに(return たびに)、変数の値は無効になってしまうのです。

ですから、add 関数内の gokei には、どんどん x の値が合計されているわけではないのです。次に add 関数が呼び出されたとき gokei は、「int gokei = 0;」で初期化されて0にあっています。

関数内で変数を宣言すると、その変数のためのメモリが確保されます。return すると、確保されたメモリは破棄されてしまいます。確保されてから破棄されるまでを、その変数の寿命といいます。また、add 関数内の gokei 変数は、main 関数から見えません(読み出したり、書き換えたりできない)。これを変数のスコープ(scope, 適用範囲)といいます。

では、関数が return しても値を保持し続けるようにするには、どうしたらよいのでしょうか。これには、変数にstaticというキーワードをつけます。これは、記憶クラス指定子(storage class specifier)と呼ばれるものです。これには、extern, static, auto, register 等があります。

auto はその変数が自動変数であることを示します。自動変数は関数内もしくはブロック内で宣言された変数で、その関数やブロック内のみで有効です。制御がその関数やブロックを離れたら破棄されます。自動変数はスタック領域と呼ばれるメモリ上に記憶されます。


ソースコード

源文件
  1|/* local01.c */                                                             
  2|
  3|#include <stdio.h>
  4|
  5|int function();
  6|
  7|int i = 10;
  8|
  9|int main(void)
 10|{
 11|  int i = 5;
 12|  {
 13|    int i = 3;
 14|    printf("main 関数の中のブロック内:i = %d\n", i);
 15|  }
 16|  printf("main関数内:i = %d\n", i);
 17|  function();
 18|
 19|  return 0;
 20|}
 21|
 22|int function()
 23|{
 24|  printf("function関数:i = %d\n", i);
 25|  return 0;                                                                 
 26|}

実行結果

main 関数の中のブロック内:i = 3
main関数内:i = 5
function関数:i = 10


static変数は、すでに述べたにプログラムが終了するまで値を保持ます。また、宣言に初期化しないと、自動的に0で初期化されます。では、span01.c を書き換えて、希望通りのをするようにしてみましょう。

ソースコード

源文件
  1|/* span02.c */
  2|
  3|#include <stdio.h>
  4|
  5|int add(int);
  6|
  7|int main(void)
  8|{
  9|  int sum;
 10|
 11|  sum = add(10);
 12|  printf("sum = %d\n", sum);
 13|
 14|  sum = add(20);
 15|  printf("sum = %d\n", sum);
 16|
 17|  sum = add(100);
 18|  printf("sum = %d\n", sum);
 19|
 20|  return 0;
 21|}
 22|
 23|int add(int x)
 24|{
 25|  static int gokei = 0;
 26|  gokei += x;                                                               
 27|  return gokei;
 28|}

実行結果

sum = 10
sum = 30
sum = 130


希望通りの結果になりましたね。

extern変数は、関数の外側で宣言し、他のソースファイルからも参照できます。

変数には寿命とスコープがある。

関数の外で宣言した変数はグローバル変数となる。

Chapter5 @ C言語目録 @ HomeWork List @ 昭亮's Homepage