問題① 円周率を表す記号定数を定義し、円の面積を求めるプログラムを作成してください。
#include <stdio.h>
#define PI 3.14159265358979323846
int main(void)
{
puts("円の半径を入力してください。");
double radius;
char str[40];
fgets(str, sizeof(str), stdin);
sscanf(str, "%lf", &radius);
printf("この円の面積は %lf です。\n", radius * radius * PI);
}実行結果:
円の半径を入力してください。
10
この円の面積は 314.159265 です。
円周率の値をどこかで調べてくれば、あとは単に #define で定義するだけです。 このとき、マクロ名は PI などの名前にします。
処理系📘によっては、<math.h> に M_PI という名前で、円周率の定義が用意されていることがありますが、これは標準のものではありません。
問題② 次のプログラムを実行すると、出力結果はどうなるか答えてください。
#include <stdio.h>
#define PUT_SW
void func(int num);
int main(void)
{
func(1);
#undef PUT_SW
func(2);
#define PUT_SW
func(3);
#undef PUT_SW
func(4);
}
void func(int num)
{
#ifdef PUT_SW
printf("%d\n", num);
#endif
}
出力されるのは、1 と 3 だと思った人は、まだプリプロセスとコンパイルを分離して考えられていません。正解は、次のようになります。
実行結果:
つまり、何も出力されません。
プリプロセッサディレクティブは、コンパイルの前段階で行われます。そこで、まずは # で始まっている行のことだけを考えます。
#define や #undef を繰り返していても、結局のところ一番のポイントは、#ifdef ~ #endif のところです。 この箇所に来たときに、PUT_SW が有効になっているかどうかだけが問題になります。
今はプリプロセスのことだけを考えているので、関数の中にいるとか、処理の流れがどうだとかは「関係ありません」。「#ifdef PUT_SW」の箇所に来た時点では、PUT_SW は最後の #undef によって無効になっているので、条件式は偽になります。
したがって、このプログラムはコンパイル段階には、次のような状態になっています。
(※stdio.h の内容がある)
void func(int num);
int main(void)
{
func(1);
func(2);
func(3);
func(4);
}
void func(int num)
{
}結局、func関数の中身は空になってしまうので、どの位置から func関数を呼び出そうと関係なく、つねに何も出力されません。
問題③ まず、次のプログラムを見てください。
#include <stdio.h>
int main(void)
{
puts("1");
puts("2");
puts("3");
puts("4");
}#if を使って、3 を出力している puts関数の呼び出しをコメントアウトしてください。さらに、その後、すべての puts関数の呼び出しをコメントアウトしてください。
/* と */ によるコメントアウトと比較すると、どのような違いがありますか?
まず、puts("3"); をコメントアウトします。
#include <stdio.h>
int main(void)
{
puts("1");
puts("2");
#if 0
puts("3");
#endif
puts("4");
}次に、すべての puts関数の呼び出しをまとめてコメントアウトします。
#include <stdio.h>
int main(void)
{
#if 0
puts("1");
puts("2");
#if 0
puts("3");
#endif
puts("4");
#endif
}実行結果:
このように、#if 0 と #endif で囲む方法であれば、入れ子📘のかたちにでもコメントアウトできます。 /* と */ で囲む方法だとうまくいきません。
#include <stdio.h>
int main(void)
{
/*
puts("1");
puts("2");
/*
puts("3");
*/
puts("4");
*/
}最後の */ よりも前で、コメントは効果は終わってしまい、最後の */ は単なる余計な文字として残ってしまいます。この余計な文字のせいで、コンパイルエラーになってしまいます。
( の直後、) の直前に空白を入れない)return 0; を削除(C言語編全体でのコードの統一)
Programming Place Plus のトップページへ
| はてなブックマーク に保存 | Facebook でシェア | X で ポスト/フォロー |
| LINE で送る | noteで書く |
|
| 管理者情報 | プライバシーポリシー |