変数の通用範囲
自動変数のことを局所変数、外部変数のことをグローバル変数(大域変数)ともいいます。
変数のスコープの範囲を図で表してみます。
赤色で囲った部分がグローバル変数の有効範囲です。
青色で囲った部分がローカル変数の有効範囲です。
この図ではローカル変数の寿命を関数内と説明しましたが、正確にはブロック内です。
ブロックとは、{}で囲まれている範囲のことを指しています。
記憶クラス
Cで扱う記憶領域は一般に、プログラム領域、静的領域、スタック領域、ヒープ領域の 4つに大別されます。
記憶クラスには、4つあり、自動、静的、外部、レジスタがあります。
記憶クラス | 記憶領域 | スコープ | 記憶クラス指定子 |
自動変数 | スタック | { } の内側 | auto( 不要 ) |
静的変数 | 静的領域 | { } の内側* | static |
外部変数 | 静的領域 | 全域 | extern** |
レジスタ変数 | レジスタまたはスタック | { } の内側 | register |
- * { }の外側で宣言された時は、その行以降
- ** 他のファイルにある時、externを付け、その変数を宣言(メモリを確保)しているファイルでは何も付けない。
自動変数は使う前に何らかの値を代入します。このことを、初期化するといいます。
静的変数は初期化の式がなくても、コンパイル時に0に初期化されます。
変数の名前
変数は名前を付けなければ、使えません。C言語では、名前(識別子)は、英字または’_’(アンダースコア)で始まり、英数字または’_’が0個以上続くという決まりになっています。’_’一つまたは二つで始まる変数は、システムに密着したデータに使います。例えば、コンパイラのプログラム等で使われます。
変数に名前を付ける時、外部変数は定義されている所から遠い所でも使われるので、その変数の用途を想像できるような名にすることが推奨されています。
例:timetable, itemindex, thisyear
自動変数は通用範囲が狭いので、何の変数かがすぐわかるので、タイピングの手間を省く意味でも、短くて良いとされています。
例:i, j, m, x, c
その場合でも、その変数がなんであるかを、瞬時に連想できるものが良いとされています。例えば、整数ならば、i、j、k、n、浮動小数点数ならば、x、y、z、文字ならば、cなどです。
#include <stdio.h> void Func(void); /* プロトタイプ宣言 */ void main(void); /* 静的変数 i と自動変数 j の値を表示する */ void Func(void) { /* i の値を読み書きできるのはこの関数の中でだけ */ /* i はずっと存在し続け、 */ static int i; /* func( ) が呼ばれる度に1増える */ auto int j; /* 自動変数は初期化しないと */ /* ゴミの値が入っている */ /* j はゴミの値が表示される */ /* 幾つになるかはわからない */ /* auto は付けなくてもよい */ /* というより、普通は付けない */ printf("i = %d j = %d\n", i, j); /* i, j の値を表示 */ i++; /* 値を1増やす */ j++; /* 値を1増やす */ } /* 関数を抜けたこの時点で、j は破壊される */ void main(void) { Func( ); /* 呼び出す度に i の値は 1 増える */ Func( ); Func( ); }
演習
渡された引数の最大値を返す関数を作成してください。(教科書p299)
ヒント:
- 最大値を記憶する変数は静的変数で、INT_MINで初期化
- 整数値入力部分は、下記の例題を参考
http://chenlab.net/2016/06/27/c-exercisesb-recursive-call/ - 終了条件について、下記の例題を参考
http://chenlab.net/2016/04/18/c-exercises-2-stdio/