Почему люди используют #ifdef для тестирования флагов объектов?
Люди рекомендуют #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
Я только обсуждаю случай тестирования флага.
Ответы
Ответ 1
Почему люди все еще используют #ifdef в этом сценарии?
Личное мнение: его немного легче контролировать из командной строки. Я предпочитаю -DOPTION
более -DOPTION=1
.
Кроме того, существование имени явно двоично. Мне не нужно обрабатывать {0, ненулевое, undefined}.
Неужели они просто не знают, что #if отлично работает на именах undefined?
Я не знал. Какова семантика этого? Является ли имя undefined равным 0? Должен ли я объяснить это парню, который с самого начала понимает препроцессор?
Или существует ли реальный недостаток для #if vs #ifdef для условной компиляции?
Для меня двоичный характер существования #ifdef/#ifndef
существования названия - это явное преимущество.
Кроме того, мое основное использование любой конструкции - включение защитных устройств. Этот шаблон является самым чистым с помощью #ifndef
.
Ответ 2
Я не могу говорить, почему люди вообще предпочитают #ifdef
более #if
, но я могу хотя бы сказать, почему я это делаю. Основываясь на интроспекции только сейчас (поскольку вы спросили - я никогда раньше не рассматривал это явно), есть две причины:
1) Я предпочитаю свои макросы (которые я стараюсь использовать сдержанно), чтобы иметь максимально понятную семантику, и, соответственно, как "свободный тип", насколько это возможно. Я предполагаю, что макросы, если они вообще имеют какой-либо тип, являются либо "бесплатными функциями типа" (обратите внимание: здесь я бы сильно предпочел шаблоны, но есть моменты для всего...) или в основном просто логические флаги. Следовательно, даже присвоение макроса макроса 1
для него растягивает его. (Например, что это значит, если у вас есть #define _cplusplus 2
? Это должно быть иначе, чем 1
?)
2) Этот последний бит о том, что они являются "флагами", согласуется с тем фактом, что я в основном использую их для вещей, которые я указываю в командной строке (или в среде IDE) в качестве условных флагов компиляции. Действительно, в моей команде разработчиков, когда мы пишем С++, мы в основном "запрещены" от использования макросов для чего-либо еще. И даже в случае условной компиляции мы стараемся избегать их, если мы можем решить проблему по-другому (например, через модульность).
Обе эти причины относятся к тому же основному предположению о том, что использование макросов следует избегать как можно больше (на С++), и поэтому не нужно сложностей типов или непрозрачной семантики. Если вы не сделаете это предположение (и это менее распространено при программировании на языке C, я знаю), то это изменяет такие вещи, что, как я полагаю, ваши точки о #if
могут иметь более сильное влияние.