読者です 読者をやめる 読者になる 読者になる

C言語 ローカル/グローバル/スタティック変数

Program C言語

C言語改訂版1 はじめてのプログラミング (CD-ROM付) (プログラミング学習シリーズ)

C言語改訂版1 はじめてのプログラミング (CD-ROM付) (プログラミング学習シリーズ)

Javaでも同様の記憶がある、変数の種類。C言語には3種類あるとの事。

  • ローカル変数:特定の関数中で有効な変数、他の関数の変数との重複許可、ローカル変数に他の関数を干渉させたい場合はポインタ変数を使用
  • グローバル変数:全ての関数中で有効な変数、重複不可
  • スタティック変数:両者の中間

Rにおいても、関数を作成するときは同様の感覚を持っているような気がする。両者の中間という概念がよくわからないが、それは手を動かして考えてみる。

ローカル変数は今までやってきたのでパス。次はグローバル変数。グローバル変数は次のようにファイルの冒頭に宣言するのが慣例のよう。

#include <stdio.h>
#include <stdlib.h>

int rdm[100];			//グローバル変数の宣言

void rnd() {
	int i;
	srand(10);

	for(i=0;i<100;i++)	{
		rdm[i] = rand();	 //rand関数は0~RAND_MAX(2147483647)の乱数を生成
		printf ("%d\n",rdm[i] );
	}
}

main () {
	rnd();
	int i;
	for(i=0;i<99;i++)		{
		if(rdm[i+1] > rdm[i]) {		//グローバル変数はmain()でも関数rnd()でも通用
			puts("fine");
		} else {
			puts("rainy");
		}
	}
}

ちなみに、ここによると、rand()は「お手軽専用」で研究活動には用いない方が良いらしい。乱数の発生は一度集中的に研究するつもり。あと、本題から話は逸れるが、コンパイル時に表示されたエラーについてはここにお世話になった。getsって使わない方がいいんですね。例の配列オーバーを誘発する関数のよう。

次はスタティック変数。「ローカル変数に近いスタティック変数」と「グローバル変数に近いスタティック変数」があるとのこと。まず前者。

#include <stdio.h>

int count() {
	static int count;	//ローカル変数に近いスタティック変数
	count++ ;
	return count;
}

main () {
	int i;
	for (i=0; i<100; i++) {
		count();	
		printf("Count is %d\n",count);	//他の関数中でも存在し続ける
	}
}

ちなみに、上記のコードはCount is 1, Count is 2, …, Count is 100を表示させたかったのですが、4198768が100回表示されます。謎です。これも初期値設定の問題か。とりあえず、後で考えることにする。

次に、「グローバル変数に近いスタティック変数」。

#include <stdio.h>

static int count;	//グローバル変数に近いスタティック変数

int cnt() {
	count++ ;
	return count;
}

main () {
	int i;
	for (i=0; i<100; i++) {
		cnt();	
		printf("Count is %d\n",count);	//他の関数中でも存在し続けるし、他の関数からでもアクセスは可能(他のファイルからのアクセスは不可)
	}
}

今度は望んだ結果が得られた。

Count is 1
Count is 2
Count is 3
Count is 4
Count is 5
Count is 6
Count is 7
Count is 8
Count is 9
(中略)
Count is 100

「ローカル変数に近いスタティック変数」は他の関数からはアクセス出来ない(もちろん他のファイルからもアクセスできない、しかし、変数を宣言したファイル内で存在し続ける)、「グローバル変数に近いスタティック変数」は他の関数からはアクセス出来る(ただし、異なるファイルからはアクセスできない)、という理解。後者の意味は理解できた。アクセスをファイル内で限定するために宣言する変数というわけか。前者って、存在意義あるんですかね…?

【追記】 気づいたこと

  • プロがおっしゃるには、「ローカル変数に近いスタティック変数」について、他の関数からのアクセスを許可しないことで品質を保証する、という意味合いがあるようだ。
  • システムの信頼性を確保するには、変数のアクセス可能領域を最適にすることが必要。むやみやたらにグローバル変数を用いると、不本意なアクセスによってプログラムが壊れることがある
  • グローバル変数についてファイル外からアクセスする場合は、冒頭にextern 変数の型 変数; という記述が必要
  • 初期値について:ローカル変数は初期値が不定、グローバル変数、スタティック変数は初期値が0