Когда нам нужен #ifdef перед #undef?

Во многих файлах C и C++ я видел такие макросы:

#ifdef X
#undef X  // no statements in between
#endif

Я чувствую, что достаточно просто написать:

#undef X

Если макрос X не был определен, то #undef не должен иметь никакого эффекта.

Можно ли можно поставить автономный #undef, если я хочу только отменить определение макроса? Делает ли это в любом случае плохую практику кодирования?


person iammilind    schedule 01.02.2012    source источник
comment
Я согласен; Я только что сделал быстрый поиск, и это поведение, похоже, согласуется со всеми основными компиляторами. Возможно, некоторые исторически не позволяли вам отменить определение неопределенного макроса? Не уверена. Я бы сказал, что это, наверное, безопасно.   -  person Anthony    schedule 01.02.2012
comment
Мне кажется, что все в порядке само по себе   -  person Jim Rhodes    schedule 01.02.2012
comment
Я думаю, что помню, по крайней мере, MSVC ошибся в этом.   -  person Xeo    schedule 01.02.2012
comment
@Xeo, может быть, в прошлом. MSDN считает, что с VS2005.   -  person Anthony    schedule 01.02.2012
comment
@anthony: Документы на самом деле говорят, что он действителен еще в VS 2003. Вероятно, он думает о VC 6, известном своим несоблюдением стандартов.   -  person Cody Gray    schedule 01.02.2012


Ответы (3)


См. ISO C99 6.10.3.5 параграф 2.

Предварительная обработка директивы формы

# undef identifier new-line

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

Даже Visual C++ 6 (известный плохим соответствием стандартам) позволяет это:

Вы также можете применить директиву #undef к идентификатору, у которого нет предыдущего определения. Это гарантирует, что идентификатор не определен. Замена макроса не выполняется в операторах #undef.

person Ken Bloom    schedule 01.02.2012
comment
Я могу подтвердить, что это точно то же самое для ISO C++11. - person Anthony; 01.02.2012

Я уверен, что это артефакт истории. Как упоминалось в ответе jdigital, во втором выпуске K&R говорится

Применение #undef к неизвестному идентификатору не является ошибкой.

Однако этого предложения нет в издании 1978 года. Я почти уверен, что компиляторы до стандарта часто выдавали ошибку, если вы пытались #undef использовать неопределенный макрос.

Кроме того, Обоснование стандарта ANSI C:

Явно разрешено использовать #undef для макроса, который не имеет текущего определения.

Я полагаю, что если бы это уже было универсальной практикой, не было бы необходимости указывать это в обосновании.

Все это говорит о том, что в современном коде это не обязательно, но и не помешает.

person Michael Burr    schedule 01.02.2012
comment
У меня нет доказательств, но я готов поспорить, что компиляторы C той эпохи (первое издание) не выдадут ошибку. Это не соответствовало бы философии Unix. - person jdigital; 01.02.2012
comment
Как это для одержимости: мне удалось найти в Google старый компилятор DeSmet-C для MS-DOS (версия 2.4 от 1984 года!), И он выдает ошибку, когда я #undef FOO -- 3 # $$ undef FOO / error:not defined - person Michael Burr; 01.02.2012
comment
Ты победил! (Люди, использующие MS-DOS, явно не поняли философии Unix.) - person jdigital; 01.02.2012
comment
@MichaelBurr: пожалуйста, оставьте свой комментарий в качестве ответа. Я хотел бы дать вам некоторую репутацию за это. - person Ken Bloom; 02.02.2012

Керниган и Ричи (2-е издание) согласны с вами.

РЕДАКТИРОВАТЬ: цитата из источника (раздел A12.3):

Контрольная строка формы

# undef идентификатор

приводит к тому, что определение препроцессора идентификатора забывается. Если не ошибочно применить #undef к неизвестному идентификатору.

person jdigital    schedule 01.02.2012
comment
Можно цитату из источника? - person Anthony; 01.02.2012
comment
@ anthony-arnold: цитата из источника по запросу. - person jdigital; 01.02.2012