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