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