Макросы пустых функций - PullRequest
       10

Макросы пустых функций

33 голосов
/ 08 февраля 2012

Если я определяю макрос функции без реального тела, это как пустая строка с компилятором (т.е. он не генерирует никаких дополнительных инструкций во время компиляции)?

Пример:

#define SomeMacro(a)

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

Ответы [ 4 ]

46 голосов
/ 08 февраля 2012

Вы абсолютно правы, пустой макрос не генерирует никакого кода.

Я видел два места, где это полезно. Первый - исключить предупреждения, когда параметр функции не используется:

#define UNUSED(x)

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

Второй - когда вы используете условные выражения, чтобы определить, должен ли быть код или нет.

#ifdef LOGGING_ENABLED
#define LOG(x) log_message(x)
#else
#define LOG(x)
#endif
18 голосов
/ 26 декабря 2012

Ваш код не совсем правильный, я предлагаю вам вставить пустые скобки в ваш макрос

#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"

6 голосов
/ 08 февраля 2012

Это верно. Ваш код расширяется до

;

после предварительной обработки.

Обратите внимание, что вы можете попросить ваш компилятор показать вам код после предварительной обработки (в gcc это опция -E; ваш компилятор может отличаться).

6 голосов
/ 08 февраля 2012

Препроцессор выполняет буквальную подстановку со всеми макросами.

Поэтому, если вы определите «пустой» макрос, то каждое место, в котором этот идентификатор появляется в вашем коде, будет заменено пустым оператором препроцессором до того, как компилятор когда-либо запустится.

Так что да. Для примера, приведенного в вашем вопросе, код не будет создан.

...