Posts Tagged #define

Cの仮引数付きマクロ(マクロ関数)について考える

今ちょうどCをまじめに勉強中。
何度目かの正直・・・。
で、仮引数付きマクロ、いわゆるマクロ関数について整理しておこうかなぁ、と。

マクロ関数の基本としては、

#include <stdio.h>
#define PI 3.141592674
#define circle(r) (r) * (r) * PI
#define echo(str) printf("%s", str)
main()
{
double radius;  // 半径
char str[] = "半径を入力して下さい\n";
echo(str);
scanf("%lf", &radius);
printf("面積は%.2fです。\n", circle(radius));
return 0;
}

とすると、

McLaren% ./marco
半径を入力して下さい
2.1
面積は13.85です。

となる。

何をやっているかと言えば、定数PIは3.141592674と定義。
問題はcircle(r) (r) * (r) * PI。
ソース内でcircle(radius)と呼び出すとその部分が(radius) * (radius) * PIと置換される。
文字通り置換されるらしい。
そのタイミングはコンパイル時。
で、それを連発すると関数呼び出しによるオーバーヘッドが無い分高速化はされるけど、ソースと実行ファイルは肥大化しますよ、と。
それはカーニハン&リッチーのプログラミング言語C(以下、K&R)に書いてある通り。
(p.109 第2版)

で、なぜ(radius) * (radius) * PI と回りくどい書き方をしているかと言うと、それもK&Rに書いてある。
仮引数r がもしhoge – 100 とかだと、r * r * PI だとhoge – 100 * hoge – 100 * PIとなる。
もうちょっと詳しく書くとhoge – (100 * hoge) – (100 * PI) となってしまう。
だからこう書かないと、期待した値にならないよ、と。
実はこのコードの初版ではそのことに気がつかずに書いていたから、急いで直したのはここだけの話w

そうそう、K&Rでは一言も「マクロ関数」とは書いていない。
あくまで「仮引数付きマクロ」とのこと。
まぁ、実際問題関数じゃないからそこは意見が分かれることなんだろうけど、所詮ニュアンスの違いじゃないの?と思ってしまう今日この頃。

そんだけ。

Post to Twitter

, , , ,

No Comments