Макро-производящие макросы в C? - PullRequest
7 голосов
/ 14 мая 2009

Я хотел бы получить препроцессор C для генерации макросов для меня (т.е. я использую только C99). Я бы написал макрос

#define make_macro(in) <...magic here...>

и когда я ставлю

make_macro(name1)
make_macro(name2)

позже в коде он расширится до

#define name1(...) name1_fn(name1_info, __VA_ARGS__)
#define name2(...) name2_fn(name2_info, __VA_ARGS__)

и тогда я смогу использовать name1 и name2 как (реализованные на макросе) функции. Я думаю, что застрял с использованием макросов на обоих этапах: имеет смысл использовать макрос для многократного повторного заполнения шаблона, и обработка переменных аргументов не будет работать, кроме как через макрос.

Так что же входит в заполнитель <... magic here ...> для этого? На этом этапе я начинаю верить, что это невозможно в C99, но, возможно, мне не хватает некоторых деталей синтаксиса.

Ответы [ 6 ]

6 голосов
/ 14 мая 2009

Это невозможно в стандартном C.

4 голосов
/ 14 мая 2009

Рассматривали ли вы использование макросов M4? Я думаю, что они доступны на большинстве платформ, поэтому это не должно быть ограничением.

Страница M4 GNU

3 голосов
/ 14 мая 2009

Это невозможно, поскольку макрос выполняется только один раз.

Это не значит, что вы не можете использовать другие макросы в вашем макросе, но вы не можете сделать

#define TEST #define HALLO 33

int x = TEST;

и ожидайте, что x будет 33 впоследствии! То, что вы получите, это синтаксическая ошибка, потому что вы пытались

int x = #define HALLO 33;

Или, возможно, компилятор уже жалуется на #define в # define.

2 голосов
/ 14 мая 2009

Как все говорили, вы не можете делать именно то, что просите.

Вы можете сделать что-то подобное, заставив препроцессор C запускаться дважды, например, с таким правилом в make-файле:

.c.pp:
   $(CPP) $< -o $@

Тогда дайте вашему файлу расширение test.pp. Makefile запустит его один раз, чтобы сгенерировать файл .c, а затем обычный запуск файла .c запустит его второй раз.

Лично я предпочел бы написать внешний скрипт на Perl или что-то подобное, чтобы сгенерировать для меня C-код; это немного чище, чем играть в игры с препроцессором Си. Это зависит от того, сколько кода мы говорим.

1 голос
/ 10 февраля 2014

Согласно C99, раздел 6.10.3.2 :

Каждый # токен предварительной обработки в списке замены для подобного макросу должен быть с последующим параметром в качестве следующего токена предварительной обработки в списке замен.

Таким образом, вы, безусловно, можете поместить #define в макрос, если у вас есть параметр с именем define, но он никогда не будет выполнять то, что вы хотите. Это часто вызывает у меня проблемы, так как мне приходится работать в C, и поэтому я не могу использовать шаблоны C ++.

0 голосов
/ 14 мая 2009

Попробуйте #define make_macro(name,...) name##_fn(name##_info, __VA_ARGS__).

Используйте вот так:

make_macro(name1)
make_macro(name2,1)

и это сгенерирует

name1_fn(name1_info)
name2_fn(name2_info,1)
...