C言語のマクロは何に役立つのか?
質問
私は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
を使うのはもう少し手間がかかります。
関連
-
[解決済み] なぜmemsetではなくbzeroを使用するのですか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] C++でextern "C "を使用した場合の効果は?
-
[解決済み] C言語のコードで「:-!」とは何ですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] マクロで無意味なdo-while文やif-else文を使っているのはなぜですか?
-
[解決済み] C++のヘッダーファイルで#ifndefと#defineが使われているのはなぜですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】C言語の「static」関数とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Cエラー [エラー] 代入_Ashesの左オペランドにlvalueが必要です-プログラマーズ・シークレット
-
#137: 式は変更可能なlvalueでなければならない問題 // 文字列配列の代入問題
-
[C] Error [Error] 代入の左オペランドとして lvalue が必要です。
-
C - 添え字の値が配列でもポインタでもベクトルでもないエラー
-
エラー: 宣言されていない識別子 'bool' の使用と C コンパイラでの問題点
-
[解決済み] stdinとSTDIN_FILENOの違いは何ですか?
-
[解決済み] なぜmemsetではなくbzeroを使用するのですか?
-
[解決済み] Linuxカーネルにおけるcontainer_ofマクロの理解
-
[解決済み] なぜC言語では構造体を頻繁にtypedefする必要があるのですか?
-
[解決済み] 2次元配列の反復処理において、ループの順序がパフォーマンスに影響するのはなぜですか?