Люди рекомендуют #ifdef для условной компиляции с широким диапазоном. A поиск #ifdef подтверждает, что его использование распространено.
Однако #ifdef NAME (или эквивалентно #if defined(NAME) и связанные с ним #ifndef NAME (и #if !defined(NAME)) имеют серьезный недостаток:
header.h
#ifndef IS_SPECIAL
#error You're not special enough
#endif
source.cpp
#include "header.h"
gcc -DIS_SPECIAL source.cpp
очевидно, будет, как и
source1.cpp
#define IS_SPECIAL 1
#include "header.h"
Но так будет
source0.cpp
#define IS_SPECIAL 0
#include "header.h"
что совершенно неправильно. И некоторые компиляторы С++ передали файл, обработанный в режиме C (из-за расширения или опции командной строки) эффективно #define __cplusplus 0. Я видел, как вещи ломаются, когда
#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif
обрабатывался в режиме C, где extern "C" является недопустимым синтаксисом, потому что __cplusplus на самом деле автоматически определяется как 0.
С другой стороны, это верно для всех компиляторов:
#if __cplusplus
extern "C" {
#endif
/* ... */
#if __cplusplus
}
#endif
Почему люди все еще используют #ifdef в этом сценарии? Просто ли они не знают, что #if отлично работает на именах undefined? Или существует ли фактический недостаток #if vs #ifdef для условной компиляции?
Очевидно, что #ifdef имеет допустимые применения, такие как предоставление значений по умолчанию для настраиваемых параметров:
#ifndef MAX_FILES
#define MAX_FILES 64
#endif
Я только обсуждаю случай тестирования флага.