Зачем использовать макрос+0!=0
в моей текущей кодовой базе я вижу следующий шаблон:
#if SOMETHING_SUPPORTED+0 != 0
...
#endif
к сожалению, это очень старая база кода и никто не знает, как и почему она началась. Я думаю, что это началось в C, и он был медленно преобразован в C с классами, и теперь он имеет тенденцию к C++
Я не вижу очевидного преимущества использования предыдущей конструкции вместо "классического", но, возможно, мне чего-то не хватает:
#if SOMETHING_SUPPORTED
...
#endif
знаете ли вы, почему бы использовать #if MACRO+0 != 0 вместо #if MACRO?
4 ответа:
ключ здесь в том, что кодовая база очень старая.
этот трюк, вероятно, существует, потому что код когда-то был портирован на компилятор с каким-то очень старым препроцессором, который не обрабатывает неопределено макросы как 0 в препроцессор
#ifусловные.то есть, по состоянию на 1989 ANSI C было стандартизировано, что если мы имеем:
#if foo + bar-xyzzy
директива подлежит замене макроса, так что если
foo,barилиxyzzyэто макросы, они заменяются. Затем все оставшиеся идентификаторы, которые не были заменены, заменен0. Так что еслиfooопределяется как42, аbarиxyzzyне определены вообще, мы получаем:#if 42 + 0 - 0а не, скажем, плохой синтаксис:
#if 42 + -или какое-то другое поведение, например диагностика о
barне определены.на препроцессоре, где неопределенные макросы обрабатываются как пробелы,
#if SOMETHING_SUPPORTEDрасширяется до просто#if, что тогда ошибочно.это единственный способ, которым это
IDENT+0трюк имеет какой-то реальный смысл. Вы просто никогда не захотите этого делать, если вы можете полагаться на то, что предварительная обработка соответствует ISO C.причина в том, что если
SOMETHING_SUPPORTEDожидается, что у него будут числовые значения, ошибочно разбросано, чтобы определить его как просто пустой. В идеале вы хотите определить, когда это произошло, и остановить компиляцию с помощью диагностический.во-вторых, если вы do поддержка такого рассеянного использования, вы почти наверняка хотите, чтобы явно определенный, но пустой символ вел себя так, как если бы он имел значение 1, а не значение 0. В противном случае, вы создаете ловушку. Кто-то может сделать это в командной строке компилятора:
-DSOMETHING_SUPPORTED=$SHELL_VAR # oops, SHELL_VAR expanded to nothingили в код:
#define SOMETHING_SUPPORTED /* oops, forgot "1" */никто не собирается добавить a
#defineили-Dдля символа с целью поворота выкл функция, которую он контролирует! Программист, который вставляет#define SOMETHING_SUPPORTEDбез1будет удивлен поведением#if SOMETHING_SUPPORTED+0который пропускает материал, который должен был быть включен.
вот почему я подозреваю, что немногие программисты C, читающие это, когда-либо видели такое использование, и почему я подозреваю, что это просто обходной путь для поведения препроцессора, чей предполагаемый эффект-пропустить блок, если
SOMETHING_SUPPORTEDотсутствует. Дело в том, что он закладывает "ловушку программиста" -это просто побочный эффект обходного пути.чтобы обойти такую проблему препроцессора без создания ловушки программиста, нужно иметь где-то в начале единицы перевода следующее:
#ifndef SOMETHING_SUPPORTED #define SOMETHING_SUPPORTED 0 #endifа потом в другом месте просто использовать
#if SOMETHING_SUPPORTED. Может быть, этот подход не приходил в голову оригинальному программисту, или, возможно, этот программист думал, что+0трюк был аккуратным, и придавал значение его самоограничению.
#if X+0 != 0отличается от#if Xв случаеXопределяется как пустой (Примечание: это отличается от случаяXне определены), например:#define X #if X // error #if X+0 != 0 // no error; test failsочень часто определяют пустые макросы: конфигурация проекта может генерировать некоторый общий заголовок, содержащий кучу строк
#define USE_FOO,#define USE_BARвключить функции, которые поддерживает система, и так далее.The
!= 0избыточна, код мог бы просто быть#if X+0.
Итак, преимущество использования
#if X+0, что еслиXопределяется как пустой, затем компиляция продолжается с пропущенным блоком, а не вызывает ошибку.является ли это хорошей идеей спорно, лично я бы использовал
#ifdefдля логических макросов типаUSE_SOME_FEATUREи#ifдля макросов, где значение может быть диапазоном целых чисел, например; и я хотел бы видеть ошибку, если я случайно использую#ifС чем-то определено как пустое.