Люди рекомендуют #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
Я только обсуждаю случай тестирования флага.