実行結果
sum = 10
sum = 20
sum = 100
add関数は、呼び出し元からもらった値をgokeiにどんどん加えていくつもりで作った関数です。例えば
- sum = add(10);
とすれば、 sum の値は10になり、次に
- sum = add(20);
とすれば、 sum の値は30になり、次に
- sum = add(100);
とすれば、sum の値は130になることを期待して作ったわけですが、結果は全然違います。
どうしたことでしょうか。実は、関数内で宣言した変数には寿命があるのです。関数が制御を戻すたびに(return たびに)、変数の値は無効になってしまうのです。
ですから、add 関数内の gokei には、どんどん x の値が合計されているわけではないのです。次に add 関数が呼び出されたとき gokei は、「int gokei = 0;」で初期化されて0にあっています。
関数内で変数を宣言すると、その変数のためのメモリが確保されます。return すると、確保されたメモリは破棄されてしまいます。確保されてから破棄されるまでを、その変数の寿命といいます。また、add 関数内の gokei 変数は、main 関数から見えません(読み出したり、書き換えたりできない)。これを変数のスコープ(scope, 適用範囲)といいます。
では、関数が return しても値を保持し続けるようにするには、どうしたらよいのでしょうか。これには、変数にstaticというキーワードをつけます。これは、記憶クラス指定子(storage class specifier)と呼ばれるものです。これには、extern, static, auto, register 等があります。
auto はその変数が自動変数であることを示します。自動変数は関数内もしくはブロック内で宣言された変数で、その関数やブロック内のみで有効です。制御がその関数やブロックを離れたら破棄されます。自動変数はスタック領域と呼ばれるメモリ上に記憶されます。
ソースコード
源文件
1|
2|
3|#include <stdio.h>
4|
5|int function();
6|
7|int i = 10;
8|
9|int main(void)
10|{
11| int i = 5;
12| {
13| int i = 3;
14| printf("main 関数の中のブロック内:i = %d\n", i);
15| }
16| printf("main関数内:i = %d\n", i);
17| function();
18|
19| return 0;
20|}
21|
22|int function()
23|{
24| printf("function関数:i = %d\n", i);
25| return 0;
26|}
|
実行結果
main 関数の中のブロック内:i = 3
main関数内:i = 5
function関数:i = 10
static変数は、すでに述べたにプログラムが終了するまで値を保持ます。また、宣言に初期化しないと、自動的に0で初期化されます。では、span01.c を書き換えて、希望通りのをするようにしてみましょう。
ソースコード
源文件
1|
2|
3|#include <stdio.h>
4|
5|int add(int);
6|
7|int main(void)
8|{
9| int sum;
10|
11| sum = add(10);
12| printf("sum = %d\n", sum);
13|
14| sum = add(20);
15| printf("sum = %d\n", sum);
16|
17| sum = add(100);
18| printf("sum = %d\n", sum);
19|
20| return 0;
21|}
22|
23|int add(int x)
24|{
25| static int gokei = 0;
26| gokei += x;
27| return gokei;
28|}
|
実行結果
sum = 10
sum = 30
sum = 130
希望通りの結果になりましたね。
extern変数は、関数の外側で宣言し、他のソースファイルからも参照できます。
変数には寿命とスコープがある。
関数の外で宣言した変数はグローバル変数となる。
Chapter5 @ C言語目録 @ HomeWork List @ 昭亮's Homepage
| | |