Я давно этим занимался, но мне стало ясно, что в макросах предварительной обработки файла aeskey.c
происходит сопоставление с образцом. Единственное, что мне удалось найти c, это это .
Pattern Matching
Оператор ##
используется для объединения двух токены в один токен. Это обеспечивает очень мощный способ сопоставления с образцом. Скажем, мы хотим написать макрос IIF
, мы могли бы написать его так:
#define IIF(cond) IIF_ ## cond
#define IIF_0(t, f) f
#define IIF_1(t, f) t
Однако в этом подходе есть одна проблема. Тонкий побочный эффект оператора ##
заключается в том, что он запрещает расширение. Вот пример:
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// This will however expand to
IIF_A()(true, false)
// This is because A() doesn't expand to 1,
// because its inhibited by the ## operator
IIF(A())(true, false)
Чтобы обойти это, используйте другое косвенное обращение. Поскольку это обычно делается, мы можем написать макрос под названием CAT
, который будет объединяться без блокировки.
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
Итак, теперь мы можем написать макрос IIF
(его сейчас называют IIF
, позже мы покажет, как определить более обобщенный способ определения макроса IF
):
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// And this will also now correctly expand to true
IIF(A())(true, false)
При сопоставлении с образцом мы можем определить другие операции, такие как COMPL
, который принимает дополнение:
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
или BITAND
:
#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y
Мы можем определить операторы увеличения и уменьшения как макросы:
#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 9
#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8