1. 記憶クラスとは
第11章でユーザ関数についての説明をしましたので、今度は関数間での変数の扱いについて説明したいと思います。
いわゆる「記憶クラス」というものなのですが、初心者にとってはわかりづらいものかもしれません。
このホームページでは分割コンパイルは扱わない予定になっておりますので、初心者がユーザ関数を同一ファイルで扱うときに必要となる記憶クラスのみを説明することにします。
2. 有効範囲
「有効範囲」とはその変数を参照できる範囲のことです。 C言語では、変数の宣言をソースプログラムのどこに書くかによって「ローカル変数」と「グローバル変数」に分けられ、この有効範囲が異なってきます。
この有効範囲は「記憶クラス」と密接な関係がありますので、まずは有効範囲から理解してください。
(1) ローカル変数(局所変数)
- 関数内で定義され、その関数内でのみ使用できます。
- 複数の関数が同一の変数名を用いたとしても衝突しません。
※ 前章までの学習で使用していた変数はすべてこのローカル変数に該当します。
(2) グローバル変数(広域変数)
- 関数外で定義され、定義以降のどの関数からでも使用できます。
- システムでグローバル変数としては1つの定義しか許されません。
※ 仮にある関数のローカル変数にグローバル変数と同一の名前が存在するときにはその関数内ではローカル変数が優先します。
(3) ローカル変数とグローバル変数の有効範囲

〇 演習問題
問1
以下のプログラムはグローバル変数に定義され、初期化された 10個の int型データの合計、平均、分散、標準偏差を求めて表示するプログラムである。
このプログラムを以下のような関数を用いて書き換えなさい。
return型 | 関数名 | 引数 | 機能 |
int | get_goukei | なし | 合計を求めて返却する |
double | get_bunsan | 平均値 | 分散を求めて返却する |
なお、n件のデータの分散と標準偏差を求める式は以下である。
分散 = { (要素0 – 平均値)2 + (要素1 – 平均値)2 +・・・+
(要素n-2 – 平均値)2 + (要素n-1 – 平均値)2 } / n
標準偏差 = √分散
#include <stdio.h>
#include <math.h>
#define N 10
int data[N] = {80, 76, 59, 87, 66, 54, 40, 78, 94, 61};
int main(void)
{
double heikin, bunsan = 0.0, hensa;
int goukei = 0;
for (int i = 0; i < N; i++) {
goukei = goukei + data[i];
}
heikin = (double) goukei / N;
for (int i = 0; i < N; i++) {
bunsan = bunsan + ( data[i] - heikin ) * ( data[i] - heikin );
}
bunsan = bunsan / N;
hensa = sqrt(bunsan);
printf("合計点 : %d\n", goukei);
printf("平均点 : %f\n", heikin);
printf("分散 : %f\n", bunsan);
printf("標準偏差 : %f\n", hensa);
return 0;
}
問2
【問1】のグローバル変数を main()関数のローカル変数に書き換えてプログラムを作り直しなさい。get_goukei() と get_bunsan() の return型と引数は都合のよいように書き換えなさい。
【問1と問2の実行結果例】
合計点 : 695
平均点 : 69.500000
分散 : 243.650000
標準偏差 : 15.609292
解答例
// 問1
#include <stdio.h>
#include <math.h>
#define N 10
int data[N] = {80, 76, 59, 87, 66, 54, 40, 78, 94, 61};
int get_goukei( void );
double get_bunsan( double avg );
int main(void)
{
double heikin, bunsan, hensa;
int goukei;
goukei = get_goukei();
heikin = (double) goukei / N;
bunsan = get_bunsan(heikin);
hensa = sqrt(bunsan);
printf("合計点 : %d\n", goukei);
printf("平均点 : %f\n", heikin);
printf("分散 : %f\n", bunsan);
printf("標準偏差 : %f\n", hensa);
return 0;
}
/***
配列の合計を求める関数
引数:なし
返却値:合計値
***/
int get_goukei( void )
{
int sum = 0;
for (int i = 0; i < N; i++) {
sum = sum + data[i];
}
return sum;
}
/***
分散を求める関数
引数:double avg; 配列要素の平均値
返却値:分散
***/
double get_bunsan(double avg)
{
double disp = 0.0;
for (int i = 0; i < N; i++) {
disp += ((data[i] - avg) * (data[i] - avg));
}
return disp / N;
}
// 問2
#include <stdio.h>
#include <math.h>
#define N 10
int get_goukei(int *p);
double get_bunsan(int *p, double avg);
int main(void)
{
double heikin, bunsan, hensa;
int goukei;
int data[N] = {80, 76, 59, 87, 66, 54, 40, 78, 94, 61};
goukei = get_goukei(data);
heikin = (double) goukei / N;
bunsan = get_bunsan(data, heikin);
hensa = sqrt(bunsan);
printf("合計点 : %d\n", goukei);
printf("平均点 : %f\n", heikin);
printf("分散 : %f\n", bunsan);
printf("標準偏差 : %f\n", hensa);
return 0;
}
/***
配列の合計を求める関数
引数:int *p; 配列の先頭要素へのポインタ
返却値:合計値
***/
int get_goukei(int *p)
{
int sum = 0;
for (int i = 0; i < N; i++) {
sum = sum + *p;
p++;
}
return sum;
}
/***
分散を求める関数
引数:int *p; 配列の先頭要素へのポインタ
double avg; 配列要素の平均値
返却値:分散
***/
double get_bunsan(int *p, double avg)
{
double disp = 0.0;
for (int i = 0; i < N; i++) {
disp += ((*p - avg) * (*p - avg));
p++;
}
return disp / N;
}
コメント