[解決済み] C言語におけるマクロと関数の比較
2022-02-11 02:26:55
質問
関数を使うよりマクロを使った方がいいというケースをよく見かけます。
関数と比較した場合のマクロのデメリットを、例を挙げて説明してください。
どのように解決するのですか?
マクロは、テキストによる置換に依存し、型チェックを行わないため、エラーが発生しやすい。例えば、このマクロ。
#define square(a) a * a
は整数で使用しても問題なく動作します。
square(5) --> 5 * 5 --> 25
が、式と一緒に使うと非常に奇妙なことになります。
square(1 + 2) --> 1 + 2 * 1 + 2 --> 1 + 2 + 2 --> 5
square(x++) --> x++ * x++ --> increments x twice
引数を括弧で囲むことは有効ですが、これらの問題が完全になくなるわけではありません。
マクロが複数のステートメントを含んでいる場合、コントロールフロー構造でトラブルになることがあります。
#define swap(x, y) t = x; x = y; y = t;
if (x < y) swap(x, y); -->
if (x < y) t = x; x = y; y = t; --> if (x < y) { t = x; } x = y; y = t;
これを解決するための通常の戦略は、ステートメントを "do { ... の中に入れることです。} while (0)" ループの中に記述することです。
同じ名前で異なるセマンティクスを持つフィールドを含む2つの構造体がある場合、同じマクロが両方に対して動作し、奇妙な結果になる可能性があります。
struct shirt
{
int numButtons;
};
struct webpage
{
int numButtons;
};
#define num_button_holes(shirt) ((shirt).numButtons * 4)
struct webpage page;
page.numButtons = 2;
num_button_holes(page) -> 8
最後に、マクロはデバッグが難しく、奇妙な構文エラーや実行時エラーが発生し、理解するために展開する必要があります(例:gcc -E)、この例のように、デバッガはマクロをステップスルーできないからです。
#define print(x, y) printf(x y) /* accidentally forgot comma */
print("foo %s", "bar") /* prints "foo %sbar" */
インライン関数と定数は、マクロのこれらの問題の多くを回避するのに役立ちますが、常に適用できるわけではありません。マクロを使用して意図的に多相性の動作を指定した場合、意図しない多相性を回避することが困難な場合があります。C++には、マクロを使わずに型安全な方法で複雑な多相構造を作成するのに役立つテンプレートなどの機能があります; Stroustrupの C++プログラミング言語 をご覧ください。
関連
-
[解決済み】「複数の定義」「最初に定義されたのはここです」エラーについて
-
[解決済み】エラー:不明な型名'bool'
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] メソッドと関数の違いは何ですか?
-
[解決済み] クロージャ」と「ラムダ」の違いは何ですか?
-
[解決済み] JavaScriptの関数をパラメータとして渡す
-
[解決済み] 関数名をその関数内から判断する(トレースバックを使用しない)。
-
[解決済み】JavaScriptの関数にデフォルトのパラメータ値を設定する
-
[解決済み】高放射能環境下で使用するアプリケーションのコンパイルについて
-
[解決済み】関数の前のエクスクラメーションマークは何をするのですか?
最新
-
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の入力の最後に期待される宣言またはステートメント
-
[解決済み】 `S_ISREG()` とは何ですか、そして何をするのですか?
-
[解決済み】式は、単純なポインタ演算を使用して完全なオブジェクト型へのポインタでなければなりません【重複】。
-
[解決済み】C言語で浮動小数点例外(コアダンプ)発生
-
[解決済み】スレッド1:EXC_BAD_ACCESS(コード=1、アドレス=0x0)標準Cメモリ問題
-
[解決済み】サイズ8の無効な読み取り - Valgrind + C
-
[解決済み】C言語で多重定義を防ぐには?
-
[解決済み】「複数の定義」「最初に定義されたのはここです」エラーについて
-
[解決済み】なぜか。"エラー: 配列型を持つ式への代入"
-
[解決済み】makefile:4。*** missing separator. 停止する