Thinkers'Studio
JavaとC言語の自習ツール
変数の値を表示する便利なマクロ
 デバッグなどで変数の中身を確認したいとき、int型ならたとえば次のような printf 文を使います。
    printf( "変数名 = %d\n", 変数名 );
 int型変数がいくつもあるなら、指定した各々の変数に応じて変数名のところが置き換わるマクロがあると、便利ですね。
 今回は、マクロのパラメタ(引数)を文字列として解釈させる方法についてです。

マクロのパラメタ(引数)を文字列化する #

 先ほどの printf文は、たとえば次のようなマクロとして定義することができます。
#define  PR_INT1(x)  printf(#x " = %d\n", (x))
 マクロのパラメタの前に # をつけると、パラメタを "" で挟んだ文字列に置換されます。
 たとえば、マクロの呼び出しがプログラム中に現われると、コンパイル時に次のように置き換えられます。
PR_INT1(num); は、printf("num" " = %d\n", (num)); へ
 ダブルクォートで囲んだ文字列が並んでいますが、C言語では隣接する文字列定数は連結されて1つの文字列になります。

プリントの変換書式も指定して便利に

 % に続く変換書式もパラメタで指定すると、便利に使えます。
#define  PR_FMT(f,x)  printf(#x " = %"#f"\n", (x))
 このマクロは、たとえば次のように置換されます。
PR_FMT(2d,num);は   printf( "num" " = %""2d""\n", (num));
PR_FMT(5.1f,val);は printf( "val" " = %""5.1f""\n", (val));

【 引数をプリントするマクロの使用例 】
 下記は、身長と体重をキーボードから指定すると、BMI 指数から体型を評価するプログラムです。
 double型の変数をプリントするマクロ、書式を指定するマクロを使って、関数に渡された引数や結果の値を表示します。
#include <stdio.h>
#define PR_DBL2(x,y) printf(#x " = %f, "#y " = %f\n",(x),(y))
#define PR_FMT(f,x)  printf(#x " = %"#f"\n", (x))

// BMI指数を求めて返す
double getBmi( double h, double w )
{
    double hm = h * 0.01;    //身長をm単位に変換する
    PR_DBL2( hm, w );
    return w / ( hm * hm );  //bmi = w/(hm * hm)
}

main()
{
    double h, w, bmi;

    printf( "身長, 体重を指定してください\n" );
    if( scanf( "%lf, %lf", &h, &w ) == 2 ) {
        bmi = getBmi( h, w );
        PR_FMT( .2f, bmi );
        if( bmi < 18.5 )      printf( "やせ型です\n" );
        else if( bmi < 25.0 ) printf( "標準です\n" );
        else                  printf( "肥満です\n" );
    }
}
実行結果
身長, 体重を指定してください
170.0, 56.5
hm = 1.700000, w = 56.500000
bmi = 19.55
標準です
 赤文字がマクロによる表示です。 それぞれ指定した変数名とともに、その値が表示されています。

(今週のクイズです)
 #define DEBUG の定義があるときだけ、getBmi や main のマクロ実行が行われるようにするには、どうすればよいでしょう?
  (答えは、次回のC言語の Tips で)

[ 関連記事 ] マクロは機械的に置換するので注意

前回の答え:(前回の問題を見る
#define LIMIT 1000000 (100万)を定義し、下記の main で求めます。 効率化の着目点は isPrimeNum と同じです。 2以外の偶数は素数でないことが分かっているので候補から外し、 それ以外を isPrimeNum に調べさせます。
main()
{
    int n;
    printf( "%dを超えない最大の素数は・・・ ", LIMIT );
    n = ( LIMIT>2&&LIMIT%2 == 0 ? LIMIT-1 : LIMIT ); 
    while( n >= 2 ) {
        if( isPrimeNum( n ) ) {
            printf( "%d\n", n ); break;
        }
        n -= 2;
    }
}