2 変数のスコープ

変数はデータを記憶するためのもの--記憶領域に名前をつけたもの--である.それには, いろいろ便利な仕組みがある.それらの仕組みは,(1)大規模なプログラムを効率的に記 述,(2)メモリー--記憶領域--を節約,(3)高速に動作させるためにある.諸君が作る小 さなプログラムであればあまり恩恵はないが,将来必ず役に立つときがくる.

2.1 宣言の場所と有効範囲

変数は,宣言する場所によって有効範囲が異なる.この有効範囲のことをこれを変数のス コープ(scope:範囲)という.有効範囲というのは,プログラム中で変数が使える場所のこ とである.具体的には,その変数を使って計算したり,表示することができる範囲で
printf("%f", hogehoge);
 

のように書いてもエラーにならない範囲である.

変数を宣言する場所,次の3箇所と考えてよい.

この3つの変数宣言の場所とスコープの関係をを図1に示す.これをしっか り理解せよ.

これが理解できたならば,図1のプログラムの実行結果が,以下のように なることが分かるであろう.自分でこのプログラムの動作を追ってみよ.



\fbox{実行結果}

fuga at main = 222
hoge at main = 111
foo at test = 333
foo at test = 111
bar at for loop = 444
bar at for loop = 444
図 1: 変数のスコープ(有効範囲)
\includegraphics[keepaspectratio, scale=1.0]{figure/scope.eps}

2.2 優先順位

どのような理由で,変数は宣言する場所でスコープが異なるのであろうか?.ちょっと考 えると,グローバル変数だけでよいように思える.小さなプログラムであれば,グローバ ル変数だけでよい.実際,グローバル変数しかないプログラミング言語もある.このよう なプログラミング言語は,大きなプログラムを作ることは不可能で,ちょっとした小さな プログラム専用である.なぜならば,グローバル変数だけだと,同じ変数名を使うことが できず,変数名の命名に大変苦労する.C言語のように宣言する場所で,変数のスコープ が異なると,同じ変数名を使うことができる.メイン関数で「hogehoge」と言う変 数を使っていても,他のユーザー定義関数などで「hogehoge」を使っても,異なっ た物として取り扱ってくれる.これは,便利な機能で複数のプログラマーがそれぞれ関数 を作成してひとつのプログラムを作る場合,各人が勝手な変数名を使うことができる.最 初の疑問「変数宣言の場所でスコープが異なる理由?」の答えは,同じ変数名を使 えることにするためで,それにより大規模なプログラムが開発できるようにしている.

それでは,「グローバル変数とローカル変数で同じ変数名を使った,どちらが実際使われ るのか?」ということになる.そのため,同じ変数名には優先順位がある.優先度の高い 順に並べると,(1)ブロック内宣言の変数,(2)ローカル変数,(3)グローバル変数となる. これを理解するために,同じ変数名を使ったプログラムをリスト1に 示す.

   1 #include <stdio.h>
   2 
   3 void test(void);               // プロトタイプ宣言
   4 
   5 int hoge=999;
   6 
   7 //===============================================
   8 // メイン関数
   9 //===============================================
  10 int main(void){
  11   int i;
  12 
  13   printf("hoge at main = %d\n", hoge);
  14 
  15   test();
  16 
  17   for(i=1; i<2; i++){
  18     int hoge=888;
  19     printf("hoge at for loop = %d\n", hoge);
  20 
  21   }
  22 
  23   return 0;
  24 }
  25 
  26 
  27 //===============================================
  28 // test  ユーザー定義関数
  29 //===============================================
  30 void test(void){
  31   int hoge=777;
  32 
  33   printf("hoge at test = %d\n", hoge);
  34   
  35 }
このプログラムを実行した結果を以下に示す.変数のスコープと優先順位が理解できたなば,こ の実行結果に納得がいくだろう.



\fbox{実行結果}

hoge at main = 999
hoge at test = 777
hoge at for loop = 888

2.3 グローバル変数の例

2.3.0.1 2つ以上の値を返す関数

これまで学習してきたユーザー定義関数は, 返せる値はひとつのみであった.グローバル変数を使うと2つ以上の値を返すことができ る3.その例をリスト 2に示す.プログラムの大事な点は次のとおりである.
   1 #include <stdio.h>
   2 #include <math.h>
   3 
   4 void shisuu_kansu(double a, double b);     // プロトタイプ宣言
   5 
   6 double value1, value2;                     // global 変数
   7 
   8 //================================================================
   9 // メイン関数
  10 //================================================================
  11 int main(void){
  12   double a, b;
  13 
  14   printf("a^bとa^(-b)を計算します\n");
  15   printf("a?\t");
  16   scanf("%lf",&a);
  17   printf("b?\t");
  18   scanf("%lf",&b);
  19 
  20   shisuu_kansu(a, b);
  21 
  22   printf("a^b = %f\n", value1);
  23   printf("a^(-b) = %f\n", value2);
  24   
  25   return 0;
  26 }
  27 
  28 //================================================================
  29 // ユーザー定義関数     a^bとa^(-b)を計算
  30 //================================================================
  31 void shisuu_kansu(double a, double b){
  32 
  33   value1=pow(a,b);
  34   value2=pow(a,-b);
  35 
  36 }



\fbox{実行結果}

x^aとx^(-a)を計算します
x?      6.3
a?      1.35
x^a = 11.998024
x^(-a) = 0.083347



ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成18年11月10日


no counter