1. ホーム
  2. c

C言語のマクロは何に役立つのか?

2023-08-13 22:19:30

質問

私はC言語を少し書きました。それが何をやっているのか一般的な考えを得るには十分に読むことができますが、マクロに遭遇するたびに完全に投げ出されてしまいました。結局、そのマクロが何であるかを思い出し、読みながら頭の中で置き換えていくしかないのです。今まで出会った直感的でわかりやすいものは、いつも小さなミニ関数のようなもので、なぜただの関数ではないのかいつも不思議に思っていました。

デバッグまたはクロス プラットフォームのビルド用に異なるビルド タイプをプリプロセッサで定義する必要性は理解できますが、任意の置換を定義する機能は、すでに難しい言語をさらに理解しにくくするためだけに役立つように思われます。

なぜ C 言語にこのような複雑なプリプロセッサが導入されたのでしょうか。そして、なぜそれがいまだに単純な if #debug スタイルの条件付きコンパイル以外の目的で使用されているように見えるのかを理解させるような使用例を誰か持っていますか?

編集してください。

多くの回答を読んで、私はまだそれを理解していません。最も一般的な回答は、コードをインライン化することです。インライン キーワードがそれを行わない場合、それを行わない正当な理由があるか、または実装を修正する必要があります。私は、(inlineが普及する前に書かれたコードは別として)このコードを本当にインライン化するために、なぜ全く別のメカニズムが必要なのか理解できません。また、quot; if its too silly to be put in a function"という考え方も理解できません。確かに、入力を受け取って出力を生成するようなコードは、関数に入れるのがベストでしょう。私は、C言語を書く際のミクロの最適化に慣れていないため、理解できないかもしれませんが、プリプロセッサは、いくつかの単純な問題に対する複雑なソリューションのように感じられます。

どのように解決するのですか?

結局、マクロが何であるかを覚えて、頭の中で置き換えながら読まなければなりません。

それはマクロの命名に悪い影響があるような気がします。プリプロセッサをエミュレートする必要はないと思うのですが、もし、それが log_function_entry() マクロであれば、プリプロセッサをエミュレートする必要はないと考えます。

今まで出会った直感的でわかりやすいものは、小さなミニ関数みたいなものばかりで、なんでただの関数じゃないんだろうといつも思ってました。

一般的なパラメータで操作する必要がない限り、通常はそうあるべきでしょう。

#define max(a,b) ((a)<(b)?(b):(a))

は、どのような型であっても < 演算子を持つすべての型に作用します。

単なる関数ではなく、マクロはソースファイルのシンボルを使って操作を実行することができます。つまり、新しい変数名を作成したり、マクロがあるソースファイルや行番号を参照したりすることができます。

C99 では、マクロはまた、次のような可変関数を呼び出すことを可能にします。 printf

#define log_message(guard,format,...) \
   if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);

log_message( foo == 7, "x %d", x)

この場合、フォーマットは次のようになります。 printf . もしガードが真であれば、メッセージを出力したファイルと行番号とともに出力します。もしこれが関数呼び出しであれば、呼び出したファイルと行を知ることはできません。 vaprintf を使うのはもう少し手間がかかります。