2015-12-15 3 views
6
кода

Im чтение C++, я нашел такое определениеНужна помощь по поводу макроопределении

#define USE_VAL(X) if (&X-1) {} 

имеет никого идею, что это значит?

+1

Вы используете это, чтобы избавиться от неиспользованного предупреждения параметра? – LogicStuff

+0

Что касается 'if' - автор, возможно, пытался это сделать: http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macroshttp://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-cc-macro – LogicStuff

+0

Я хочу знать, для чего это используется, потому что у меня есть код, который хотел бы работать с этим кодом. –

ответ

7

Основываясь на названии, это выглядит как способ избавиться от предупреждения «неиспользуемая переменная». Предполагаемое использование, вероятно, что-то вроде этого:

int function(int i) 
{ 
    USE_VAL(i) 
    return 42; 
} 

Без этого, вы можете получить предупреждение компилятора, что параметр i не используется внутри функции.

Однако это довольно опасный способ обойти это, потому что он вводит Undefined Behavior в код (арифметика указателя за пределами фактического массива не определена стандартом). Можно добавить 1 к адресу объекта, но не вычесть 1. Конечно, с + 1 вместо - 1 компилятор мог тогда предупредить о том, что «условие всегда истинно». Это возможно, что оптимизатор удалит весь if, и код останется в силе, но оптимизаторы становятся лучше использовать «неопределенное поведение не может произойти», что действительно может испортить код совершенно неожиданно.

Не говоря уже о том, что operator& может быть перегружен для соответствующего типа, что может привести к нежелательным побочным эффектам.

Есть более эффективные способы реализации такой функциональности, такие как литье в void:

#define USE_VAL(X) static_cast<void>(X) 

Однако мое личное предпочтение закомментировать имя параметра в определении функции, например:

int function(int /*i*/) 
{ 
    return 42; 
} 

Преимущество этого в том, что оно фактически предотвращает случайное использование параметра после передачи его макросу.

+0

Да, для этого последнего подхода. Это, безусловно, самый простой и не включает ** добавление ** кода, который намеренно ничего не делает, чтобы успокоить предупреждение компилятора. –

1

Обычно необходимо избегать предупреждения о неиспользованном возврате. Даже если обычная идиома «литой на пустоту» обычно работает для неиспользуемых функциональных параметров, gcc с -pedantic особенно строг при игнорировании возвращаемых значений таких функций, как fread (в общем, функции, отмеченные __attribute__((warn_unused_result))), поэтому «подделка if» часто используется для обмана компилятора, думая, что вы что-то делаете с возвращаемым значением.

+0

Вы не можете взять адрес rvalue, так что это не может работать для большинства возвращаемых значений. – Angew

0

Макрос - это предпроцессорная директива, означающая, что везде, где он используется, он будет заменен соответствующим фрагментом кода.

и здесь после USE_VAL (X) пространство объясняет, что сделает USE_VAL (X).

сначала он берет адрес x, а затем вычитает из него 1. если это 0, ничего не делайте.

где USE_VAL (X) будет использоваться он будет заменен, если (& X-1) {}

+0

Макросы не являются функциями. – LogicStuff

+0

есть макрос не функция. но для недоразумения вы можете подумать, используя эту концепцию. –

+0

@ KashifArif Нет, NO, ** NO **. Не думайте о макросах как о функциях. Они * даже не удаленно закрыты. * Макрос является чисто синтаксической заменой. Размышление о макросах, таких как функции, приводит ко всем видам ошибок и недоразумений. – Angew

Смежные вопросы