Spec-Zone.ru › GCC 11 CPP

Далее: Заголовки оболочки, Предыдущее: Альтернативы оболочке #ifndef, Выше: Файлы заголовков [Оглавление][Индекс]

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-11.4.0/cpp/Computed-Includes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API