C言語-変数の有効範囲
前へ 目次へ 次へ 

3 変数の有効範囲

 C言語では、プログラム中で使用する変数は、使用する前に宣言しなければならない。宣言した変数は、プログラムのどの範囲で有効なのか等を調べる。

3.1 局所変数(ローカル変数)

関数の引数と別々の関数内で同じ変数名を使用する。[pro3-1.c]

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
#include <stdio.h>
int main(void)
{
    void test_func(int);
    int a, b;
 
    a = 100;
    b = 101;
    printf("main 1 a=%d b=%d\n", a, b);
    test_func(a);
    printf("main 2 a=%d b=%d\n", a, b);
    return(0);
}
void test_func(int a)
{
    int b;
 
    b = 2 * a;
    a = 123;
    printf("test_func a=%d b=%d\n", a, b);
}


実行結果

main 1 a=100 b=101
test_func a=123 b=200
main 2 a=100 b=101

 7行目で変数aに100を格納し、10行目で関数test_funcを呼び出している。変数aの値は、関数test_funcの引数(変数)aに渡され、19行目でその変数aに 123を格納しているが、mainに戻ったときの変数aの値は、関数を呼び出す前の値、100のままである。同様に、8行目で変数bに101を格納し、関数test_funcの中で宣言した変数bに18行目で変数aの2倍を格納しているが、mainに戻ったときの変数bの値は、関数を呼び出す前の値、101のままである。
 このように、別々の関数で同じ変数名を使用しても違う変数として扱われる。


ブロック文内で同じ変数名を使用する。[pro3-2.c]

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
#include <stdio.h>
void main(void)
{
    int a, b, c;
 
    a = 100;
    b = 300;
    c = a + b;
    printf("No.1 a=%d b=%d c=%d\n", a, b, c);
    {
       int a, c;
 
        a = 200;
        b = 400;
        c = a + b;
        printf("No.2 a=%d b=%d c=%d\n", a, b, c);
    }
    printf("No.3 a=%d b=%d c=%d\n", a, b, c);
}
実行結果

No.1 a=100 b=300 c=400
No.2 a=200 b=400 c=600
No.3 a=100 b=400 c=400


 

3.2 大域変数(グローバル変数)

 ケースによっては、変数をプログラム全体で使用できるようにしたいときもある。このようなときに、グローバル変数を使用する。
 グローバル変数は、関数の外で宣言し、宣言した位置からプログラムファイルの終わりまでが有効範囲である。

グローバル変数を使用する。[pro3-3.c]

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
#include <stdio.h>
int b;    /* ←グローバル変数の宣言 */
int main(void)
{
    void test_func(int);
 
   int a;
    a = 100;
    printf("main 1 a=%d b=%d\n", a, b);
    b = 101;
    printf("main 2 a=%d b=%d\n", a, b);
    test_func(a);
    printf("main 3 a=%d b=%d\n", a, b);
    return(0);
}
void test_func(int a)
{
    a = 123;
    b = 999;
    printf("test_func a=%d b=%d\n", a, b);
}
実行結果

main 1 a=100 b=0
main 2 a=100 b=101
test_func a=123 b=999
main 3 a=100 b=999

 関数test_func内では、変数bが宣言されていないが、コンパイルエラーは出ない。
関数内の19行目で変数bに999を格納し、mainに戻って13行目で変数bの値を表示すると999と表示されている。このようにmainと関数test_funcの変数bは同じものとして扱われている。
 9行目までに変数bには値を格納していないが、0が表示されている。

 このようにグローバル変数は宣言されると0(文字型は\0)で初期化される。


グローバル変数と同名の変数を使用する。[pro3-4.c]

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
#include <stdio.h>
int b;        /* グローバル変数の宣言 */
int main(void)
{
    void test_func(int);
    int a;
 
    a = 100;
    printf("main 1 a=%d b=%d\n", a, b);
    b = 101;
    printf("main 2 a=%d b=%d\n", a, b);
    test_func(a);
    printf("main 3 a=%d b=%d\n", a, b);
    return(0);
}
 
void test_func(int a)
{
    int b;
 
    a = 123;
    b = 999;
    printf("test_func a=%d b=%d\n", a, b);
}
実行結果

main 1 a=100 b=0
main 2 a=100 b=101
test_func a=123 b=999
main 3 a=100 b=101

 pro3-3.cとほとんど同じであるが、18行目でグローバル変数bと同名のローカル変数bを宣言している。この場合、関数test_func内では、関数内で宣言されたローカル変数bが有効になっている。


3.3 ローカル変数の有効期間

 ローカル変数は、正式には自動変数(オート変数)といい、これまで普通に関数内で宣言していた変数である。
 例えば、整数型の変数aの宣言を int a; と記述してきた。この変数aをオート変数といい、 auto int a; と記述しても良い。
 このオート変数は、宣言された関数が実行されている間だけ有効である。

オート変数の有効期間を調べる。[pro3-5.c]

 各変数のアドレスを表示させている。アドレスの値は、実行環境(コンパイラやコンピュータの機種など)で異なる。

 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
#include <stdio.h>
int main(void)
{
    void test_func(void);
    void test_func2(void);
    int a;

    printf("main a=%X\n", &a);
    test_func();
    test_func2();
    test_func();
    printf("main a=%X\n", &a);
    return(0);
}
void test_func(void)
{
    int c;

    printf("test_func c=%X\n", &c);
}
void test_func2(void)
{
    int z;

    printf("test_func2-1 z=%X\n", &z);
    test_func();
    printf("test_func2-2 z=%X\n", &z);
}
実行結果

main a=F98
test_func c=F92
test_func2-1 z=F92
test_func c=F8C
test_func2-2 z=F92
test_func c=F92
main a=F98

 6行目、17行目、23行目で宣言されている変数がオート変数である。
 8行目で表示している変数が&aと記述されている。この & は、アドレス演算子で、変数aの値が格納されるアドレスを取得するためのものである。書式を%Xとしているので、アドレスの値が16進数で表示される。
 17行目で宣言されている変数cは、9行目で関数test_funcが呼び出されたときに変数cのための領域が確保される。そして、20行目で関数が終わり、mainに戻るときに確保されていた変数cの領域は開放される。
 9行目で関数test_funcを呼び出したときの変数cのアドレスは、F92番地(処理環境によって異なる)であった。10行目で関数test_func2を呼び出したときの変数zのアドレスもF92番地である。これは、9行目で呼び出した関数test_funcの変数cの領域がmainに戻るときに解放され、10行目で呼び出した関数test_func2の変数zの領域として、たまたま同じ番地が確保されたものである。
 関数test_func2の26行目で関数test_funcを呼び出したときの変数cのアドレスは、F8C番地になっている。
関数mainで宣言した変数aのアドレスは、プログラム終了まで同じF98番地である。
 このように、関数内のオート変数は、呼び出されるごとに領域が確保される。呼び出しの順序が違うと、確保される変数の領域が異なる。


3.4 静的変数(スタティック変数)

 オート変数とは逆に、関数から呼び出し側に戻っても、関数内で宣言された変数の領域を開放しない変数がある。これをスタティック変数といい、変数宣言の最初にstaticを付けて宣言する。
 スタティック変数は、プログラムが終了するまで、その領域が確保されている。また、スタティック変数の宣言が最初に処理されたときに、その変数の領域が確保されるとともに0(文字の場合は\0)に初期化される。

スタティック変数の有効期間を調べる。[pro3-6.c]

 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
#include <stdio.h>
int main(void)
{
   void test_func(void);
   void test_func2(void);
   int a;

   printf("main a=%X\n", &a);
   test_func();
   test_func2();
   test_func();
   printf("main a=%X\n", &a);
   return(0);
}
void test_func(void)
{
   static int c;

   printf("test_func c=%X\n", &c);
}
void test_func2(void)
{
    static int z;

    printf("test_func2-1 z=%X\n", &z);
    test_func();
    printf("test_func2-2 z=%X\n", &z);
}
実行結果

main a=FA8
test_func c=468
test_func2-1 z=46A
test_func c=468
test_func2-2 z=46A
test_func c=468
main a=FA8

 9行目で関数test_funcを呼び出したときの変数cのアドレスは468番地である。
 10行目で関数test_func2を呼び出したときの変数zのアドレスは46A番地である。オート変数のときとは違って、27行目でtest_funcを呼び出したときの変数cのアドレスは、元の468番地のままである。



前へ 目次へ 次へ 
Copyright © 2001 Hiroshi Masuda 

 

 

inserted by FC2 system