МАСКА (...) макрос с неопределенным количеством аргументов (в C)

(Извините за плохой английский язык.)

Мне нужен макрос МАСКА таким образом что:

  • MASK(a) expands to (1<<(a))
  • MASK(a,b) expands to (1<<(a) | 1<<(b))
  • MASK(a,b,c) expands to (1<<(a) | 1<<(b) | 1<<(c))
  • etc.

Is it possible to define such macro in C preprocessor? Maybe can help some GCC extensions? Or maybe is it possible to implement MASK(x) with single argument such that MASK((a,b)) expands to (1<<(a) | 1<<(b)), etc.

ADDED. I'm not interested as implement MASK as a function.

1
nl ja de
Ваше требование то, чтобы макрос расширил точно тот путь (другими словами, это производит константу), или было бы хорошо, если расширяется до вызова функции? Последний может быть сделан с макросом C99 variadic.
добавлено автор Chris, источник
@Chris: I' m знают, что я могу осуществить МАСКУ как подставляемая функция с ... . Кроме того, я думаю, что хорошие компиляторы как GCC оптимизируют требование, поскольку это будет explictly, письменный (1 <<(a)) |... . Так, I' m интересный только с препроцессором .
добавлено автор user1150105, источник

1 ответы

Да, это возможно, без любых расширений, принимая почти полностью C99 совместимый препроцессор, таких как ГНУ CPP (как используется GCC/G ++).

Here are a few different solutions using the brilliant Order library. You will need to add #include to use them.

Со всего один #define :

#define MASK(...) (ORDER_PP(8seq_for_each_with_delimiter( \
    8fn(8N, 8print((1<<) 8tuple(8N))), \
    8emit(8quote(|)), \
    8tuple_to_seq(8quote((__VA_ARGS__))))))

Для скорости компилятора и ремонтопригодности:

#define GEN_MASK(x) 1<<(x)
#define ORDER_PP_DEF_8mask ORDER_PP_FN(8fn(8N, \
    8emit(8quote(GEN_MASK),8tuple(8N))))
#define MASK(...) (ORDER_PP(\
    8seq_for_each_with_delimiter(8mask, 8emit(8quote(|)), \
    8tuple_to_seq(8quote((__VA_ARGS__))))))

Используя обобщение для подобных проблем:

#define MAP_DELIMITED(f,d, ...) ORDER_PP(\
    8seq_for_each_with_delimiter(f, \
    8emit(8quote(d)), \
    8tuple_to_seq(8quote((__VA_ARGS__)))))
#define MASK(...) (MAP_DELIMITED( \
    8fn(8N, 8print((1<<) 8tuple(8N))), \
    |, \
    __VA_ARGS__))

Заказ на самом деле осуществляет функциональный язык высокого уровня в препроцессоре, позволяя намного более сложный макрос, чем вы думали бы возможные. repo в вышеупомянутой связи включает много примеров и источник к документации.

0
добавлено