If-директива макроса сравнения - PullRequest
25 голосов
/ 20 марта 2020

Почему выполняется условие #if в следующем коде:

#include <iostream>
#define VALUE foo    

int main() {    
#if VALUE == bar
    std::cout << "WORKS!" << std::endl;
#endif // VALUE
}

Ответы [ 4 ]

26 голосов
/ 20 марта 2020

Страница на cppreference.com сообщает:

После всех расширений макросов и вычисления выражений и выражений __has_include (начиная с C ++ 17), любой идентификатор, который не является логический литерал заменяется числом 0 (это включает в себя идентификаторы, которые являются лексическими ключевыми словами, но не альтернативными токенами, такими как и).

Таким образом, foo и bar заменяются на 0 .

15 голосов
/ 20 марта 2020

В операторе #if любой идентификатор, который остается после подстановки макроса (за исключением true и false), заменяется константой 0. Таким образом, ваша директива становится

#if 0 == 0

, что верно.

14 голосов
/ 20 марта 2020

Это потому, что ни foo, ни bar не было дано никакого определения или значения - поэтому они одинаковы (то есть заменены значением "0"). Компиляторы будут предупреждать об этом.

Компилятор MSVC (Visual Studio 2019) выдает следующее:

предупреждение C4668: 'foo' не определен как макрос препроцессора, заменяя на '0' для ' # если / # Элиф» предупреждение C4668: 'bar' не определен как макрос препроцессора, заменяя на '0' для '# if / # elif'

Так что VALUE присваивается значение '0' (по умолчанию для foo) и bar также имеет «0», поэтому VALUE == bar оценивается как «ИСТИНА».

Аналогично, clang-cl выдает следующее:

предупреждение: 'foo' не определено, имеет значение 0 [-Wundef] предупреждение: 'bar' не определен, имеет значение 0 [-Wundef]

0 голосов
/ 01 апреля 2020

Чтобы достичь sh того, что вы хотите, попробуйте следующее:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

В этом случае вы можете отключить операторы отладки, изменив «define» на «undef».

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

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

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

, а затем вызвать компилятор с опцией, такой как - DDEBUG = 0

Посмотрите главу о защитном программировании у Стива МакКоннелла, "Код завершен".

...