Является ли #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.