Логическое значение в ifdef: «#ifdef A && B» то же самое, что «#if defined (A) && defined (B)»?

83

В C ++ это:

#ifdef A && B

такой же как:

#if defined(A) && defined(B)

?

Я думал, что это не так, но я не смог найти разницы с моим компилятором (VS2005).

Criddell
источник
1
возможный дубликат: stackoverflow.com/questions/965700/… Я вижу, что это C и C ++, но препроцессоры в основном такие же: stackoverflow.com/questions/5085533/…
Ciro Santilli 郝海东 冠状 病 六四 事件
Будет ли кто-нибудь цитировать и интерпретировать стандарт, чтобы решить, законен он или нет (он точно не должен работать, но нужно ли его компилировать)? Я не могу этого сделать после 15 минут чтения главы «16 директив предварительной обработки».
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

92

Они не то же самое. Первый не работает (тестировал в gcc 4.4.1). Сообщение об ошибке было:

test.cc:1:15: предупреждение: лишние токены в конце директивы #ifdef

Если вы хотите проверить, определено ли несколько вещей, используйте второй.

Эван Теран
источник
Спасибо за проверку. Я использую компилятор Microsoft, и он, кажется, позволяет это, но мне это показалось неправильным.
criddell
2
Вы не можете доказать вещи, используя какой-то один компилятор. См. Стандарт, в котором указано, что это недопустимо.
Гонки легкости на орбите
@LightnessRacesinOrbit Однако некоторые компиляторы расширяют стандарт. Утверждение «это работает в определенном компиляторе» не является попыткой доказать, что это действительно так; он отмечает, что определенный компилятор определенным образом расширяет стандарт.
Иск Фонда Моники
@QPaysTaxes: Согласен, но в этом ответе этого не происходит. Он отвечает на вопрос, который начинается «в C ++ ....» с того, что кажется общим фактом о C ++. На первый взгляд, Эван проверил свою теорию на одном компиляторе, а затем предположил, что она верна для всех, в качестве гарантии самого языка. Если бы он определил, что это поведение является расширением GCC, и сказал: «Это расширение GCC» (со ссылкой на справочные материалы), тогда все было бы хорошо! (хотя на самом деле это не ответ на этот конкретный вопрос)
Lightness Races in Orbit
1
Хотя ни количество положительных тестов не может «доказать» , что он является действительным, один отрицательный достаточно , чтобы доказать , что это не так , или что это , по крайней мере , не рекомендуется использовать. Хотя было бы неплохо сослаться на стандарт, доказательство того, что он не работает хотя бы в одном крупном компиляторе, является достаточным доказательством, чтобы сказать «это не работает» для целей этого обсуждения.
zeel
48

Условная компиляция

Вы можете использовать определенный оператор в директиве #if для использования выражений, которые оцениваются как 0 или 1 в строке препроцессора. Это избавляет вас от использования вложенных директив предварительной обработки. Скобки вокруг идентификатора необязательны. Например:

#if defined (MAX) && ! defined (MIN)  

Без использования определенного оператора вам придется включить следующие две директивы для выполнения приведенного выше примера:

#ifdef max 
#ifndef min
Светлозар Ангелов
источник
2
Хотя то, что вы говорите, правильно, это вообще не отвечает на вопрос, он спросил, одинаковы ли эти двое ... это не так.
Эван Теран,
1
Я думаю, там написано «они не такие же», вы можете видеть, что в нем объясняется, как сделать эквивалент #if defined (COND_A) && defined (COND_B), который отличается от #ifdef COND_A && COND_B
Ангелов
В любом случае, это полезное замечание.
Пол Масри-Стоун
2

Следующие результаты такие же:

1.

#define A
#define B
#if(defined A && defined B)
printf("define test");
#endif

2.

#ifdef A
#ifdef B
printf("define test");
#endif
#endif
путь хороший
источник
1
Не могли бы вы добавить комментарий, чтобы описать, как это отвечает на вопрос, это не ясно из вашего ответа.
Джеймс Вуд,
Этот ответ, хотя и является технически правильным, не дает точного ответа на вопрос и подразумевает неправильное использование. Хотя два блока будут делать одно и то же, вложение двух if - это не то же самое, что использование &&. Другие условия, например #else, могут вызвать проблему. Только первый вариант означает именно то, о чем просил спрашивающий.
zeel
1

Для тех, кто может искать, например (UNIX / g ++), который немного отличается от OP, это может помочь:

`

#if(defined A && defined B && defined C)
    const string foo = "xyz";
#else
#if(defined A && defined B)
    const string foo = "xy";
#else
#if(defined A && defined C)
    const string foo = "xz";
#else
#ifdef A
    const string foo = "x";
#endif
#endif
#endif
#endif
MikeB
источник
Почему бы просто не использовать #elif вместо #else #if и миллиард # endif в конце ...?
Эллиотт,
-3

По состоянию на VS2015 ничего из вышеперечисленного не работает. Правильная директива:

#if (MAX && !MIN)

подробнее здесь

Fabri
источник
2
Вы связались с документацией C #, а не C ++.
Revolver_Ocelot