X-макрос
Макросы X — это идиоматическое использование языка программирования макросов для создания списковых структур данных или кода. Они наиболее полезны, когда по крайней мере некоторые списки не могут быть составлены путем индексации, например, во время компиляции . Они обеспечивают надежную поддержку параллельных списков, соответствующие элементы которых должны быть объявлены или выполнены в одном и том же порядке.
Примеры таких списков, в частности, включают инициализацию массивов вместе с объявлениями констант перечисления и прототипов функций; генерация последовательностей операторов и переключение рычагов; и т. д.
Использование макросов X началось в 1960-х годах. [1] Он по-прежнему полезен в современных языках программирования C и C++ , но остается относительно неизвестным. [2] [3]
Выполнение
[ редактировать ]Макрос-приложение X состоит из двух частей:
- Определение элементов списка.
- Расширение(я) списка для создания фрагментов объявлений или утверждений.
Список определяется макросом или заголовочным файлом (с именем, LIST
), который сам по себе не генерирует код, а просто состоит из последовательности вызовов макроса (классически называемого " X
") с данными элементов. Каждое расширение LIST
предшествует определение X
с синтаксисом элемента списка. Вызов LIST
расширяется X
для каждого элемента списка.
Пример 1
[ редактировать ]В этом примере определяется список переменных, автоматически создаются их объявления и функция для их вывода.
Сначала определение списка. Записи списка могут содержать несколько аргументов, но здесь используется только имя переменной.
#define LIST_OF_VARIABLES \
X(value1) \
X(value2) \
X(value3)
Затем мы расширяем этот список, чтобы сгенерировать объявления переменных:
#define X(name) int name;
LIST_OF_VARIABLES
#undef X
Аналогичным образом мы можем создать функцию, которая печатает переменные и их значения:
void print_variables(void)
{
#define X(name) printf("%s = %d\n", #name, name);
LIST_OF_VARIABLES
#undef X
}
При запуске через препроцессор C генерируется следующий код. Для удобства чтения были добавлены разрывы строк и отступы, хотя на самом деле они не генерируются препроцессором:
int value1;
int value2;
int value3;
void print_variables(void)
{
printf("%s = %d\n", "value1", value1);
printf("%s = %d\n", "value2", value2);
printf("%s = %d\n", "value3", value3);
}
Пример 2 с макросом X в качестве аргумента
[ редактировать ]Целью этого примера является улучшение читаемости использования макроса X за счет:
- Префикс имени макроса, определяющего список, "FOR_".
- Передайте имя рабочего макроса в макрос списка. Это позволит избежать определения макроса с непонятным именем (X) и избавит от необходимости его отмены.
- Используйте синтаксис аргументов макроса с переменным числом аргументов "..." в рабочих макросах, чтобы иметь возможность принимать больше аргументов, чем необходимо. Это позволяет сопровождающему кода добавлять столбцы в список без необходимости обновлять все определения макросов.
- Используйте имя «DO» в качестве имени макроса, аргумента макроса списка.
#define FOR_LIST_OF_VARIABLES(DO) \
DO(id1, name1) \
DO(id2, name2) \
DO(id3, name3) \
Как и выше, выполните этот список, чтобы сгенерировать объявления переменных:
#define DEFINE_NAME_VAR(id, name, ...) int name;
FOR_LIST_OF_VARIABLES( DEFINE_NAME_VAR )
или объявить перечисление:
#define DEFINE_ENUMERATION(id, name, ...) name = id,
enum my_id_list_type {
FOR_LIST_OF_VARIABLES( DEFINE_ENUMERATION )
}
Аналогичным образом мы можем сгенерировать функцию, которая печатает переменные и их имена:
void print_variables(void)
{
#define PRINT_NAME_AND_VALUE(id, name, ...) printf("%s = %d\n", #name, name);
FOR_LIST_OF_VARIABLES( PRINT_NAME_AND_VALUE )
}
Дальнейшее чтение
[ редактировать ]Ссылки
[ редактировать ]- ^ Мейерс, Рэнди. Новые макросы C:X . Доктор Добб, 2001 год.
- ^ Брайт, Уолтер. X-макрос . Цифровой Марс 2010
- ^ Лукас, Эндрю. Уменьшите количество ошибок кодирования на языке C с помощью макросов X. Embedded.com 2013 г.