変数のスコープ

Last-modified: 2022-04-19 (火) 11:51:04
 

目的

変数の種類とスコープについて理解すること。

変数の種類

変数には大きく分けて、次の2種類があります。

  • ローカル変数
  • グローバル変数

今まで扱ってきた変数は、すべてローカル変数です。

ローカル変数とは

ローカル変数は、基本的にブロック {} の先頭で宣言します。
そして、宣言したブロック内部のみで利用が可能です。

例1

main 関数の中で宣言したものは、その外では使用できません。

 #include <stdio.h>

void hoge(){
    printf("%d\n", a); // コンパイルエラー
}

int main(){
    int a;

    a = 256;
    hoge();

    return 0;
}

例2

このように if 文の中でも宣言できます。
同名の変数がある場合、一番内側で宣言されたものが使用されます。

int a = 2; // このように変数は宣言時に初期化できます

if(1){
    int a = 4;

    printf("%d\n", a); // 4 が表示される
}

例3

関数に渡した引数は、その関数内部のみで利用可能な変数に代入されています。

 #include <stdio.h>

void hoge(int a){ // a は関数 hoge 内部でのみ有効
    a = 1024;
}

int main(){
    int a = 512;

    hoge(a);
    printf("%d\n", a); // 512 が表示される

    return 0;
}

グローバル変数

プログラムのどこからでも利用できる変数を、グローバル変数といいます。
グローバル変数は便利ですが、バグの原因になりやすいため使用は慎重に行います。

グローバル変数はローカル変数とは違い、自動的にゼロで初期化されます
また、グローバル変数の宣言は、すべての関数の外側で行います。

 #include <stdio.h>

int count; // グローバル変数の宣言

void increment(){
    ++count;
}

int main(){

    printf("%d\n", count); // 0

    increment();

    printf("%d\n", count); // 1

    return 0;
}

課題

課題1

出力される数値を予想しなさい。
また、実際に実行してその予想が正しかったのか確認しなさい。

 #include <stdio.h>

int g;

void func(int a, int g){
    printf("%d\n", g);
    printf("%d\n", a);
    ++g;
}

int main(){
    int a = g;

    { // ブロック、if(1){ ~ } と同じ意味です
        int a = 1;

        printf("%d\n", g);
        printf("%d\n", a);

        func(g, a);
    }

    printf("%d\n", g);
    printf("%d\n", a);

    return 0;
}

課題2

グローバル変数を用いて、次のようなプログラムを作りなさい。

  1. プログラムは初期値がゼロの整数を保持している
  2. ユーザーが ++ と入力したら、その整数をインクリメントする
  3. ユーザーが -- と入力したら、その整数をデクリメントする
  4. インクリメント、デクリメントの際に現在保持している整数を表示する
  5. ユーザーの入力は n 回行われる

このプログラムでは、次の変数及び関数を必ず用いること
もちろん、これ以外の変数や関数も自由に用いてよい。

  • グローバル変数 current
    整数の保持に使用する。
  • 関数 increment, decrement
    インクリメント、デクリメント処理はこの関数で行う。
    次のプロトタイプ宣言で表される。
    void increment();
    void decrement();

実行例

1行目はユーザーの入力の個数 n。
以降、入力のたびに保持している整数を出力すること。

./a.out
4
++
1
++
2
++
3
++
4
./a.out
4
--
-1
--
-2
++
-1
++
0