【基礎から学ぶプログラミング言語】 C言語/ローカル変数とグローバル変数について

IT
スポンサーリンク
スポンサーリンク
スポンサーリンク

私たちは日常生活で何気なくパソコンやスマートフォンというコンピュータを使用しています。
これらのコンピュータが普通に動作しているのは、そのようにプログラミング言語が記述されているからです。
本記事は、そんなプログラミング言語について実際に学びながら要点をまとめていったメモという位置付けになります。
私は専攻が電気でプログラムに関しては全くの初心者ですので、同様に初心者の方には理解しやすくなっているかと思います。

今回は、「C言語/ローカル変数とグローバル変数」についての説明です。

1.初めに

これまで様々な関数の使い方について説明していきましたが、その中で自由に変数を定義してきましたよね?
ユーザー定義関数も扱うようになってくるとこの変数に関する考え方を確立しておいた方が良くなってくるので、ここでローカル変数グローバル変数について説明を挟もうと思います。

2.ローカル変数とは?

まずは、以下のようなプログラムを記述してみます。

#include<stdio.h>

void sample1(int, int);
void sample2();

void main() {
int a = 1 , b = 2;
printf(“mainを処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“main実行完了\n\n”);
sample1(3, 4);
sample2();
}

void sample1 (int a, int b) {
printf(“sample1を処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“sample1実行完了\n\n”);
}

void sample2() {
int a = 5, b = 6;
printf(“sample2を処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“sample2実行完了\n\n”);
}

図1

大きく分けるとmainとユーザー定義関数sample1とユーザー定義関数sample2で構成されているのがわかりますね。

大まかには同じ処理を繰り返すようにしているだけなのですが、何か違和感がありませんか?
変数aとbが何回も登場しているんですよ。

これまでの説明では意図的に変数に指定する文字列は被らないようにしていたのですが、実は中括弧で閉じた関数内で指定した変数はその処理内でのみ有効な変数となります
つまり、mainの中で使用している変数a・b、sample1の中で使用している変数a・b、sample2の中で使用している変数a・bは全く別物の変数a・bとして認識されるんです。
このような変数のことをローカル変数と呼びます。
中括弧内という[local(地元)]でのみ通じる変数というネーミングです。

また、プログラム内で変数が有効な範囲のことはスコープと呼びます。

近所に鈴木さん家族が複数存在したとしたら、鈴木家が「○○さん家の鈴木一家」と「△△さん家の鈴木一家」に分かれるようなものです。
同じ呼び名でも違うものを指している事象って案外身の回りに存在するんです。
それらがローカル変数のイメージというわけです。

このプログラムを実行した結果は以下の通りです。

図2

それぞれの関数内で定義・初期化したローカル変数a・bの値をprintfで表示したのが、このプログラムなわけです。
この結果を見ると、各関数内では以下のように初期化されていることが読み取れます。

  • main:変数a=1、b=2
  • sample1:変数a=3、b=4
  • sample1:変数a=5、b=6

実際にそのようになっているのか確認してみましょう。

まず、7行目で【int a = 1 , b = 2;】と記述されています。
この記述はmainのスコープなので、main関数におけるローカル変数a=1、b=2になることがわかります。
ここで定義したローカル変数a・bは9行目で呼び出されているので、10行目までの処理が実行されると以下の部分まで実行されることがわかります。

mainを処理…
ローカル変数 a = 1 、b = 2
main実行完了

次に、11行目でsample1を実行しています。
この時に【sample1(3, 4);】と入力しているので、15行目の【void sample1 (int a, int b) 】の形に当て嵌められてsample1におけるローカル変数a=3、b=4が定義・初期化されます。
後はこのローカル変数を17行目で読み出しているだけなので、以下のように表示されます。

sample1を処理…
ローカル変数 a = 3 、b = 4
sample1実行完了

11行目を実行すると真下の12行目に移動し、sample2が実行されます。
sample2はその中括弧内の22行目にて変数a・bを定義・初期化しています。
つまり、sample2におけるローカル変数a=5、b=6になるわけです。
このローカル変数が出力されて以下の部分が表示されます。

sample2を処理…
ローカル変数 a = 5 、b = 6
sample2実行完了

同じ名称の変数を使用しているけど、それぞれ全くの別物として機能しているでしょう?
これがローカル変数なのです。

3.グローバル変数とは?

ローカル変数が[local(地元)]という狭い範囲内で機能する変数だったので、グローバル変数がどのようなものを指すのか予想が付いている人もいるかと思います。
[gloval(世界的な・全体的な)]ですからね。

グローバル変数は、今開いているソースコード全体に通用する変数です。
ローカル変数はmain・ユーザー定義関数sample1・ユーザー定義関数sample2の各々の関数内部でのみ有効な変数でしたが、グローバル変数はこの3つの中でも共通した変数になるんです。

では、グローバル変数はどのようなものなのか、先程のプログラムに書き足す形で実際に確認してみましょう。

#include<stdio.h>

int c = 0;

void sample1(int, int);
void sample2();

void main() {
int a = 1 , b = 2;
printf(“mainを処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“グローバル変数 c = %d\n”, c);
printf(“main実行完了\n\n”);
sample1(3, 4);
sample2();
}

void sample1 (int a, int b) {
printf(“sample1を処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“グローバル変数 c = %d\n”, c);
printf(“sample1実行完了\n\n”);
}

void sample2() {
int a = 5, b = 6;
printf(“sample2を処理…\n”);
printf(“ローカル変数 a = %d 、b = %d\n”, a, b);
printf(“グローバル変数 c = %d\n”, c);
printf(“sample2実行完了\n\n”);
}

図3

注目すべきは初っ端の3行目です。
特に関数を書いているわけでもなく、ただ変数cが定義・初期化されていますよね?
これがグローバル変数です。
ここにグローバル変数を定義すると、このソースコード内ならどこで読み出しても同じ値になるのです。
3行目では【int c = 0;】としているので、変数cはどこでも0になるのです。

それを確認するために、main・ユーザー定義関数sample1・ユーザー定義関数sample2内に【printf(“グローバル変数 c = %d\n”, c);】という記述を付け足しましたので、このプログラムを実行すると以下のようになります。

図4

どの関数内でもグローバル変数cは0と認識されているでしょう?

ちなみに、グローバル変数はどこでも共通するので、どこかで値を代入して変更したら、その結果が全体に反映されます。
例えば、9行目と10行目の間に【c = 100;】と記述して実行すると、実行結果は以下のように変化します。

図5

【c = 100;】は「グローバル変数cに100を代入する」という意味なので、その結果が全体に反映されているでしょう?
どこかでうっかり変更してしまうと大変なことになりますので、この点には注意しましょう。

4.ローカル変数とグローバル変数の大きな違い

ローカル変数とグローバル変数がどのようなものなのかはわかってもらえたかと思いますが、この2種類の変数にはもう1点大きな違いがあります。
それは、メモリの占有です。

簡単に言うと、ローカル変数は関数が呼び出されている間のみ有効になってメモリを占有し、グローバル変数はプログラムの実行中はずっとメモリを占有します。

ローカル変数の場合、仮にsample1を呼び出したとすると、そのsample1実行中はその中のローカル変数a・bが有効になってメモリを占有します。
ですが、sample1の実行を終えたら、もうその情報は不要と判断して占有されたメモリが解放されます。
つまり、必要な時だけメモリを使うのがローカル変数というわけです。

反面、グローバル変数の場合はmainを実行している最中でも、sample1を実行している最中でも、常にメモリを占有します。
必要不必要とか関係なくずっと使い続けるのがグローバル変数なのです。

基本的にはプログラムのメモリ占有率は抑えた方が良いので、大きなプログラムになってくるとグローバル変数ばかり使うわけにはいかなくなってくるんです。
だから、ローカル変数とグローバル変数はうまく使い分けていく必要があります。
必要な理由がなければ、基本はローカル変数を使用しておくのがベストです。

仕事が無い時は体力温存に休むのがローカル変数、仕事が無い時も何かあった時用に常にスタンバっているのがグローバル変数みたいなイメージでいいと思います。
ずっと気を張り詰めていると良くないでしょう?
まあ、場合によってはそうした方が良い場合もあるからグローバル変数も存在するんでしょうけど。

以上、C言語/ローカル変数とグローバル変数についての説明でした。