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. Чтобы свести к минимуму риск различных интерпретаций вычисленных включений разными компиляторами, рекомендуется использовать только один макрос-объект, который расширяется до строковой константы. Это также позволит уменьшить путаницу для людей, читающих вашу программу.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.4/cpp/Computed-Includes.html