Відповіді:
На сторінці cppreference.com зазначено:
Після всього розширення та оцінки визначених і __has_include (оскільки C ++ 17) виразів, будь-який ідентифікатор, який не є булевим буквалом, замінюється числом 0 (сюди входять ідентифікатори, які є лексично ключовими словами, але не альтернативними лексемами, як і ).
Тож обидва fooі barзамінюються 0.
У #ifзаяві будь-який ідентифікатор, який залишається після макрозаміни (крім trueі false), замінюється постійним 0. Так ваша директива стає
#if 0 == 0
що правда.
Це пояснюється тим, що ні їм, fooні їм barне було дано жодного визначення чи значення - значить, вони однакові (тобто замінені на значення "0"). Компілятори будуть попереджувати про це.
MSVCКомпілятор (Visual Studio 2019) дає наступне:
попередження C4668: "foo" не визначається як макрос препроцесора, замінюючи "0" для "# if / # elif"
попередження C4668: "bar" не визначається як макрос препроцесора, замінюючи "0" для "#if / # еліф '
Отже VALUE, дається значення "0" (за замовчуванням для foo), а barтакож "0", тому VALUE == barоцінюється як "ІСТИНА".
Аналогічно clang-clдає наступне:
попередження: 'foo' не визначено, оцінюється до 0 [-Wundef]
попередження: 'bar' не визначено, оцінюється до 0 [-Wundef]
MSVCта та clang-clце попередження можна відключити (конкретно, або встановивши відповідний "рівень" попередження).
Щоб виконати те, що ви хочете, спробуйте:
#include <iostream>
#define DEBUG
int main() {
#ifdef DEBUG
std::cout << "WORKS!" << std::endl;
#endif
}
У цьому випадку ви можете вимкнути оператори налагодження, змінивши "визначити" на "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
Ознайомтеся з розділом «Оборонне програмування» у Стіві МакКоннел «Код завершений».