6

Сегодня я наткнулся на некоторый код C++, который содержит пункт #ifdef, как это:#ifdef с несколькими токенами, является ли это законным?

#ifdef DISABLE_UNTIL OTHER_CODE_IS_READY 
    foo(); 
#endif 

Примечание пространство между «DISABLE_UNTIL» и «OTHER_CODE_IS_READY». По существу, в строке #ifdef есть два токена.

Мой вопрос в том, что это законный код на C++? (g ++ компилирует его без каких-либо ошибок и, по-видимому, просто игнорирует второй токен). И если это законно, должен ли второй токен повлиять?

+1

Каждая версия г ++ Я попытался предупреждает об этом, от 2.8.1 до 4.8.1, предупреждает об этом: «предупреждение: мусор в конце аргумента #ifdef», «предупреждение: дополнительные токены в конце директивы #ifdef» или «предупреждение: дополнительные токены в конце директивы #ifdef [включено по умолчанию]», , Как вы не получили диагностику? –

+0

@Keith: 'g ++ myprogram.cpp -o myprogram | grep!warning' –

+0

@LightnessRacesinOrbit: Это не будет отфильтровывать предупреждения (синтаксис 'grep' неверен, а gcc записывает диагностику в' stderr'). В любом случае, я думаю, вы спекулируете; Я хотел бы знать, как ОП не получил предупреждения. OP: Вы намеренно отключили предупреждения? –

ответ

6

[C++11 16.1], [C++11 16.5] и, между прочим, [C99 6.10.1/4] все говорят, что это недействительно.

если-группы:
# ifпостоянное выражение новой строкигруппа неавтоматического
# ifdefидентификатор новой строкигруппа неавтоматического
# ifndef идентификатор новой строкигруппа неавтоматического

только один идентификатор является законным.

Собственная документация GCC agrees.

My own tests предположить, что принят только первый идентификатор, а второй просто отбрасывается; это может быть облегчение реализации, но стандарт требует диагностики здесь, поэтому вы должны увидеть это, когда используете флаг -pedantic не менее & dagger;.

#include <iostream> 
using namespace std; 

#define A 
#define B 

int main() { 
    #ifdef A 
    std::cout << "a "; 
    #endif 

    #ifdef B 
    std::cout << "b "; 
    #endif 

    #ifdef C 
    std::cout << "c "; 
    #endif 

    #ifdef B C 
    std::cout << "bc "; 
    #endif 

    #ifdef C B 
    std::cout << "cb "; 
    #endif 

    return 0; 
} 

// Output: "a b bc" 
// Note: "cb" *not* output 

& кинжалом; Установка Colillu GCC испускает его with or without -pedantic.

+0

«* и, конечно, стандарт не требует прямой диагностики здесь * '- Стандарт требует диагностики для любого нарушения правила синтаксиса. –

+0

@Keith: О да, вы правы ('[C++ 11: 1.4/2]'). Я всегда думал о диагностике как о по умолчанию «по умолчанию» для стандартных правил, тогда как на самом деле все наоборот. Спасибо. –

10

Синтаксис, который вы опубликовали, не является законным, и предполагаемое значение неясно.

В зависимости от того, что вы надеетесь достичь, можете ли вы использовать || или &&, чтобы объединить их?
(конечно, если это чужой код, я бы просто отказаться от него, как нарушение/непригодной)

#if defined(DISABLE_UNTIL) || defined(OTHER_CODE_IS_READY) 
    foo(); 
#endif 
+2

Вы ответили на другой вопрос очень хорошо. –

+1

И как это отвечает на вопрос «если это законно»? – P0W

+0

Я не уверен, что автор кода надеялся выполнить ... Я подозреваю, что это была просто опечатка (он случайно набрал пробел, а не подстрочный). –

Смежные вопросы