2.6 Вычисляемые включения
Иногда необходимо выбрать один из нескольких заголовочных файлов для включения в вашу программу. Например, они могут указывать параметры конфигурации, используемые в разных операционных системах. Вы можете сделать это с помощью ряда условных операторов,
#if SYSTEM_1 # include "system_1.h" #elif SYSTEM_2 # include "system_2.h" #elif SYSTEM_3 … #endif
Что быстро становится утомительным. Вместо этого препроцессор предлагает возможность использования макроса для имени заголовочного файла. Это называется вычисляемым включением. Вместо записи имени заголовочного файла в качестве непосредственного аргумента ‘#include’, вы просто помещаете имя макроса:
#define SYSTEM_H "system_1.h" … #include SYSTEM_H
SYSTEM_H будет расширен, и препроцессор будет искать system_1.h, как если бы ‘#include’ было написано именно таким образом изначально. SYSTEM_H может быть определен вашим Makefile с опцией -D.
Вы должны быть внимательны при определении макроса. ‘#define’ сохраняет токены, а не текст. Препроцессор не может знать, что макрос будет использоваться в качестве аргумента ‘#include’, поэтому он генерирует обычные токены, а не имя заголовочного файла. Это вряд ли вызовет проблемы, если вы используете включения в двойных кавычках, которые достаточно близки к строковым константам. Однако, если вы используете угловые скобки, у вас могут возникнуть трудности.
Синтаксис вычисляемого включения фактически немного более общий, чем указанное выше. Если первый не-пробельный символ после ‘#include’ не ‘"’ или ‘<’, то вся строка макро-расширяется как обычный текст.
Если расширение приводит к единственной строковой константе, содержимое этой строковой константы является файлом, подлежащим включению. CPP не перепроверяет строку на наличие вложенных кавычек, но также не обрабатывает обратные слэши в строке. Поэтому
#define HEADER "a\"b" #include HEADER
ищет файл с именем a\"b. CPP ищет файл в соответствии с правилами для включений в двойных кавычках.
Если расширение приводит к потоку токенов, начинающемуся с токена ‘<’ и включающему токен ‘>’, то токены между ‘<’ и первым ‘>’ объединяются для формирования имени файла, подлежащего включению. Любые пробелы между токенами сводятся к одному пробелу; затем любой пробел после начального ‘<’ сохраняется, но пробел перед закрывающим ‘>’ игнорируется. CPP ищет файл в соответствии с правилами для включений в угловых скобках.
В любом случае, если в строке есть какие-либо токены после имени файла, возникает ошибка, и директива не обрабатывается. Также ошибка возникает, если результат расширения не соответствует ни одному из двух ожидаемых форматов.
Эти правила являются реализационно-зависимым поведением в соответствии со стандартом C. Чтобы минимизировать риск того, что разные компиляторы будут интерпретировать ваши вычисляемые включения по-разному, мы рекомендуем использовать только один макрос типа объект, который расширяется до строковой константы. Это также минимизирует путаницу для людей, читающих вашу программу.
Далее: Заголовочные файлы-обертки, Предыдущее: Альтернативы заголовочным файлам-обёрткам #ifndef, Вверх: Заголовочные файлы [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-9.5.0/cpp/Computed-Includes.html