Programming Place Plus トップページ – C言語編 – 第23章
問題① 円周率を表す記号定数を定義し、円の面積を求めるプログラムを作成してください。
#include <stdio.h>
#define PI 3.14159265358979323846
int main(void)
{
( "円の半径を入力してください。" );
putsdouble radius;
char str[40];
( str, sizeof(str), stdin );
fgets( str, "%lf", &radius );
sscanf
( "この円の面積は %f です。\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言語編全体でのコードの統一)’2018/2/27 全面的に文章を見直し、修正を行った。
’2009/8/13 新規作成。
Programming Place Plus のトップページへ