Является ли #if определенным MACRO эквивалентным #ifdef MACRO?
У меня есть код, который должен иметь два режима: debug и подробный. Я определяю их в своем файле заголовка как,
#define verbose TRUE
#define debug TRUE
В моем коде до сих пор я только что использовал
#if(debug)
//code
#endif
но более правильно использовать
#ifdef debug
// code
#endif
Я прочитал кое-что о макросах препроцессора, но в то время это не имело смысла. Итак, у меня вопрос: Is #if defined MACRO
эквивалентен #ifdef MACRO
? и что лучше включить/отключить определенный раздел кода?
Ответы
Ответ 1
#ifdef MACRO
#if defined (MACRO)
сделает то же самое. Однако определенный (MACRO) - это просто выражение, которое оценивает 0 или 1 внутри #if и может быть объединено с другими выражениями. Например
#if defined (MACRO) && ! defined (MACRO2)
// Do this
#else
// Do that
#endif
Попробуйте сделать это с помощью #ifdef - вы не можете, если ваш код не будет действительно неуклюжим.
Ответ 2
#if defined(MACRO)
совпадает с #ifdef MACRO
, но длиннее. С другой стороны, это позволяет добавлять дополнительные условия с помощью ||
или &&
.
#if MACRO
похож на #ifdef MACRO
, но не на 100%. Если MACRO
- 0
, то #if MACRO
будет отрицательным - для него требуется MACRO
, а не 0
. #ifdef
проверяет, определено ли это даже без значения (#define MACRO
).
Современно использовать #if
и включать/отключать определения со значением 1 или 0:
#define FLAG_X 1 // or 0
Ответ 3
Нет, они совсем не эквивалентны. Разветвление #if MACRO
компилируется, если MACRO
оценивается как ненулевое. С другой стороны, ветвь #ifdef MACRO
компилируется, если MACRO
определена, независимо от того, что она оценивает. Так
#include <stdio.h>
#define VAR_SET_TO_TRUE 1
#define VAR_SET_TO_FALSE 0
int main()
{
#if VAR_SET_TO_TRUE
printf("#if VAR_SET_TO_TRUE\n");
#endif
#if VAR_SET_TO_FALSE
printf("#if VAR_SET_TO_FALSE\n");
#endif
#if VAR_UNSET
printf("#if VAR_UNSET\n");
#endif
#ifdef VAR_SET_TO_TRUE
printf("#ifdef VAR_SET_TO_TRUE\n");
#endif
#ifdef VAR_SET_TO_FALSE
printf("#ifdef VAR_SET_TO_FALSE\n");
#endif
#ifdef VAR_UNSET
printf("#ifdef VAR_UNSET\n");
#endif
}
выводит
#if VAR_SET_TO_TRUE
#ifdef VAR_SET_TO_TRUE
#ifdef VAR_SET_TO_FALSE
Обратите внимание, что строка printf("#ifdef VAR_SET_TO_FALSE\n");
скомпилирована, а строка printf("#if VAR_SET_TO_FALSE\n");
- нет. Первый компилируется, потому что VAR_SET_TO_FALSE
имеет определенный, хотя его значение false
.
Ответ 4
Если я правильно читаю ваш вопрос, заголовок вводит в заблуждение, он должен быть
Is #if MACRO equivalent to #ifdef MACRO?
Они не эквивалентны, но могут (и часто) использоваться для указания двоичных режимов, которые либо включены, либо выключены. Выбор, на мой взгляд, является вопросом личных предпочтений.
Вы используете первый вариант и имеете
#define verbose true
или
#define verbose false
а затем проверьте режим, используя
#if verbose
или
#if !verbose
На самом деле, я бы рекомендовал использовать TRUE или 1 вместо true и FALSE или 0 вместо false, потому что true и false являются (или могут быть) значениями C/С++, а препроцессор не имеет доступ к значениям C/С++.
В любом случае, другой общий способ указать двоичные режимы - либо определить флаг, либо оставить его undefined, и в этом случае вы можете либо
#define verbose any thing (including nothing) goes here
или оставьте #define.
а затем вы можете проверить, определен ли флаг, либо с помощью
#ifdef verbose
или его эквивалент
#if defined(verbose)
ПРИМЕЧАНИЕ. В этом случае вы не проверяете значение флага, который вам нужен, только чтобы проверить, определено ли оно.
Если это более удобно, вы также можете проверить, установлен ли флаг undefined с помощью
#ifndef verbose
или его эквивалент
#if !defined(verbose)
Ответ 5
Если у нас хватит мозгов, мы можем придумать разницу. Но он неясен и включает в себя поведение undefined, поэтому это не имеет никакого значения, если все, о чем мы заботимся, заключается в том, является ли код строго соответствующим ISO C.
Форма #if defined ...
восприимчива к поведению по-другому, если ранее был обработан макрос #define defined ...
. В стандарте ISO C99 было написано в отношении директив #if
и #elif
:
До оценки макрокоманды в списке токенов предварительной обработки, которые станут выражением управляющей константы, заменяются (за исключением тех имен макросов, которые были изменены определенным унарным оператором), как и в обычном тексте.
Не указано, что унарный оператор defined
должен распознаваться и защищаться от обработки как макроса; это всего лишь один из "токенов предварительной обработки", которые станут... выражением ". Оператор defined
распознается на этом этапе только в целях защиты своего аргумента от расширения.
Если определение define
в качестве макроса просто разрешено стоять, а вхождения defined
впоследствии заменяются (в том числе в аргументах директив #if
preprocessing), что мешает #if defined
, но не влияет на #ifdef
.
Возможно, эта область языка была затянута с C99.