web-dev-qa-db-ja.com

空の関数マクロ

実際の本体なしで関数マクロを定義すると、コンパイラーで空の文字列のようになりますか(つまり、コンパイル時に追加の命令が生成されません)?

例:

#define SomeMacro(a)

SomeMacro("hello"); // This line doesn't add any instructions, does it?

空のマクロはコードを生成しません。

これが役立つ2つの場所を見てきました。 1つは、関数パラメーターが使用されていない場合の警告を排除することです。

#define UNUSED(x)

int foo(int UNUSED(value))
{
    return 42;
}

2つ目は、条件文を使用してコードがあるかどうかを判断する場合です。

#ifdef LOGGING_ENABLED
#define LOG(x) log_message(x)
#else
#define LOG(x)
#endif
48
Mark Ransom

あなたのコードは完全に正しくありません、私はあなたのマクロに空の括弧を置くことをお勧めします

#define somemacro(a) {}

その理由は簡単です、あなたのコードははるかに安全です!

この例を見てみましょう:

if(Value)
    somemacro(a)
else
    somemacro(b)

マクロが空の場合、コードはコンパイルされません! (「else」の前にプライマリ式が必要です)。とにかく、特定のスタイルルールでは、作成する必要があります

if(Value)
{
    somemacro(a)
}
else
{
    somemacro(a)
}

それは問題ではありません。

別のオプションは、「;」を使用することです。 "{}"の代わりに、同じオプションでそのオプションを指定すると、コンパイル時に警告が表示されますが、中括弧は警告もエラーも発生しません。 (セミコロンは警告を出してもなお良い);)

次のケースを取ります

if(value)
    somemacro(a);
else
    somemacro(b);

に拡大します

if(value)
{};
else
{};

コンパイルできません!

だからマクロは悪だ

(マクロは単純なテキスト置換であるため、ダムのルールは、常に手動でコードを置き換えて何が起こるかを確認することです。展開されたコードを表示するためにマクロを置き換えるツールもあります。)

完全に安全なマクロがあるかどうかを推測しますか?はい、「NOP」と呼ばれています

#define somemacro(a) ((void)0)

いずれの場合でも機能します(コンパイラのソースファイルでもそれをNOPとして使用します。たとえば、 "assert.h"だけを見てください。

19
CoffeDeveloper

プリプロセッサは、すべてのマクロでリテラル置換を実行します。

したがって、「空の」マクロを定義すると、コンパイラーが実行される前に、プリプロセッサーによって、コード内でそのIDが現れるそれぞれの場所が空のステートメントに置き換えられます。

あ、はい。質問の例ではコードは生成されません。

6
Cody Gray

そのとおりです。あなたのコードは

;

前処理後。

コンパイラーにコードafter前処理(gccでは、これは-Eオプション;コンパイラは異なる場合があります)。

6
Greg Hewgill