Что касается многих вопросов, ответ на этот вопрос зависит . Вместо того, чтобы сказать, что лучше, я привел примеры и цели, где один лучше другого.
И препроцессор, и константа имеют свои собственные места соответствующего использования.
В случае предварительной обработки код удаляется до начала компиляции. Следовательно, он лучше всего подходит для ситуаций, когда ожидается, что код не будет скомпилирован . Это может повлиять на структуру модуля, зависимости и может позволить выбрать лучшие сегменты кода для аспектов производительности. В следующих случаях нужно делить код только по препроцессору.
Многоплатформенный код:
например, когда код компилируется на разных платформах, когда код зависит от конкретных номеров версий ОС (или даже от версии компилятора - хотя это очень редко). Например, когда вы имеете дело с непоследовательными бинарными аналогами кода - они должны быть отделены от препроцессоров, а не констант. Или, если вы компилируете код для Windows, а Linux и некоторые системные вызовы очень разные.
Экспериментальные исправления.
Другим случаем, когда это оправдано, является наличие экспериментального кода, который является рискованным, или определенных основных модулей, которые необходимо исключить, которые будут иметь существенные различия в ссылках или производительности. Причина, по которой можно захотеть отключить код с помощью препроцессора, а не скрывать его под if (), заключается в том, что мы не можем быть уверены в ошибках, внесенных этим конкретным набором изменений, и работаем на экспериментальной основе. Если это не удается, мы должны сделать только одно: отключить этот код в производственной среде, кроме перезаписи. Некоторое время идеально использовать #if 0
для комментирования всего кода.
Работа с зависимостями: еще
одна причина, по которой вам может понадобиться сгенерировать. Например, если вы не хотите поддерживать изображения JPEG, вы можете помочь избавиться от компиляции этого модуля / заглушки, и в конечном итоге библиотека не будет (статически или динамически) связываться с этим модуль. Иногда пакеты запускаются ./configure
для определения доступности такой зависимости, и если библиотеки отсутствуют (или пользователь не хочет их включать), такая функциональность отключается автоматически без привязки к этой библиотеке. Здесь всегда полезно, если эти директивы генерируются автоматически.
Лицензирование.
Одним из очень интересных примеров директивы препроцессора является ffmpeg . Он имеет кодеки, которые могут потенциально нарушать патенты при его использовании. Если вы загрузите исходный код и скомпилируете его для установки, он спросит вас, хотите ли вы или удалите такие вещи. Сохраняя коды , спрятанные под некоторыми , если условия по- прежнему могут посадить Вас в суде!
Код копировать-вставить:
ака макросы. Это не совет по чрезмерному использованию макросов - просто у макросов гораздо более эффективный способ применения эквивалента после копирования . Но используйте это с большой осторожностью; и используйте его, если знаете, что делаете. Константы, конечно, не могут этого сделать. Но можно также использовать inline
функции, если это легко сделать.
Так когда вы используете константы?
Почти везде.
Более аккуратный поток кода:
в общем, когда вы используете константы, он почти неотличим от обычных переменных и, следовательно, лучше читаемый код. Если вы пишете подпрограмму, которая состоит из 75 строк, используйте 3 или 4 строки после каждых 10 строк, а #ifdef ОЧЕНЬ не сможет прочитать . Вероятно, с заданной первичной константой, управляемой #ifdef, и использующей ее в любом естественном потоке.
Код с хорошим отступом : все директивы препроцессора, никогда не работают хорошо с другим кодом с хорошим отступом . Даже если ваш компилятор допускает отступ #def, препроцессор Pre-ANSI C не допускал пробела между началом строки и символом "#"; ведущий "#" должен был всегда находиться в первом столбце.
Конфигурация:
Еще одна причина, по которой константы / или переменные имеют смысл, заключается в том, что они могут легко эволюционировать от связи либо с глобальными, либо в будущем могут быть расширены для получения из файлов конфигурации.
И последнее:
никогда не ИСПОЛЬЗУЙТЕ директивы препроцессора #ifdef
для #endif
пересечения области или { ... }
. то есть начало #ifdef
или конец #endif
по разные стороны { ... }
. Это очень плохо; это может сбивать с толку, это может быть иногда опасно.
Это, конечно, не исчерпывающий список, но он показывает серьезную разницу в том, какой метод лучше использовать. На самом деле дело не в том, что лучше , а в том, что более естественно использовать в данном контексте.