問題① 次のプログラムの実行結果を答えてください。
#include <stdio.h>
int num = 100;
void func(void);
int main(void)
{
{
int num = 300;
("%d\n", num);
printf}
();
func("%d\n", num);
printf}
void func(void)
{
int num = 200;
("%d\n", num);
printf{
("%d\n", num);
printf}
}
実行結果は次のようになります。
実行結果:
300
200
200
100
main関数の最初にある printf関数では、同じブロック内にある変数num の値が出力されます。
次に、func関数内にある 2つの printf関数ですが、これはいずれも func関数内の変数num の値が出力されます。
main関数に戻ってきた後の printf関数では、その位置から可視なのはグローバル変数の num だけですから、グローバル変数の num の値が出力されます。
ルールとしては、今実行している箇所と同じブロックが優先され、そこから外へ外へとスコープを広げて、宣言を探しにいくということです。
問題② 呼び出すたびに 0、1、2 … という具合に増加する整数を出力する countup_print関数を作ってください。
静的ローカル変数を使って実現できます。
#include <stdio.h>
void countup_print(void);
int main(void)
{
for (int i = 0; i < 5; ++i) {
();
countup_print}
}
void countup_print(void)
{
static int num = 0;
("%d\n", num);
printf++num;
}
実行結果:
0
1
2
3
4
静的ローカル変数は、静的記憶域期間を持つため、プログラムの開始直後にオブジェクトが構築され、プログラムが終了するまでメモリに存在し続けます。そのため、関数を抜けても、最後に記憶していた値を失いません。
便利なようにも思える反面、明確に不便なところもあって、たとえばカウントを 0 に戻したいと思ったとき、自然に実現する方法がありません。せいぜい、引数で指示を与えるくらいのことしかできません。
void countup_print(_Bool reset)
{
static int num = 0;
if (reset) {
= 0;
num }
("%d\n", num);
printf++num;
}
こういうことをしていると、プログラムはどんどん複雑化していきますし、使い方を間違える可能性も高くなります。
グローバル変数を使って実現すれば、0 に戻す機能を付けやすくなりますが、スコープを狭く保つべしという基本原則からは遠ざかることになります。
#include <stdio.h>
int g_num = 0;
void countup_print(void);
void countup_reset(void);
int main(void)
{
for (int i = 0; i < 5; ++i) {
();
countup_print}
();
countup_resetfor (int i = 0; i < 5; ++i) {
();
countup_print}
}
void countup_print(void)
{
("%d\n", g_num);
printf++g_num;
}
void countup_reset(void)
{
= 0;
g_num }
実行結果:
0
1
2
3
4
0
1
2
3
4
問題③ 次のプログラムで、コメントの箇所にある printf関数が、グローバル変数の方の num の値を出力できるようにプログラムを書き換えてください。
#include <stdio.h>
int num = 100;
int main(void)
{
int num;
= 10;
num ("%d\n", num);
printf("%d\n", num); // グローバル変数の方を出力したい
printf}
1つの方法は、ブロックで囲むことです。
#include <stdio.h>
int num = 100;
int main(void)
{
{
int num;
= 10;
num ("%d\n", num);
printf}
("%d\n", num); // グローバル変数の方を出力したい
printf}
実行結果:
10
100
変数名が被らないのが一番良いです。できるなら、グローバル変数の名前を変えましょう。g
などのグローバル変数であることをあらわすプリフィックスを付けたり、長い名前にしたりします。
#include <stdio.h>
int g_num = 100;
int main(void)
{
int num;
= 10;
num ("%d\n", num);
printf("%d\n", g_num); // グローバル変数の方を出力したい
printf}
実行結果:
10
100
(
の直後、)
の直前に空白を入れない)return 0;
を削除(C言語編全体でのコードの統一)全面的に文章を見直し、修正を行った。
サンプルプログラムに含まれていた余計なコードを削除。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |