Я пытаюсь написать макрос, который упрощает установку нескольких битов в целое число. Это обычно происходит в коде микроконтроллера при инициализации регистров конфигурации. Например, можно настроить 8-разрядный таймер, установив 3 бита в регистре TCCR0A
так:Написание переменного макроса, который устанавливает определенные биты в целое число (бит-маска)
// WGM01, WGM00 and COM0A1 are constants between 0 and 7
// There are hundreds of these constants defined in avr-libc
TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0A1);
// Another way to write this:
#define _BV(bit) (1 << (bit)) // <-- defined in avr-libc
TCCR0A |= _BV(WGM01) | _BV(WGM00) | _BV(COM0A1);
Однако, я считаю, это намного проще, чтобы написать что-то вроде этого:
TCCR0A |= BITS(WGM01, WGM00, COM0A1); // <- Variable # of arguments please!
Поскольку я не могу представить, что об этом никто не думал, я искал вокруг, но ничего не нашел, что делает именно это. Интересно, возможно ли это вообще, но я все равно дал ему выстрел, читая https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html и https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms.
Вот что я пробовал до сих пор. Я предполагаю, что решение должно быть рекурсивным макросом, но не очень далеко, пытаясь его правильно развернуть. Поскольку все мои регистры имеют длину 8 бит, должно быть достаточно 8 проходов расширения (для первой попытки).
#define BITS_EVAL(...) BITS_EVAL1(BITS_EVAL1(BITS_EVAL1(__VA_ARGS__)))
#define BITS_EVAL1(...) BITS_EVAL2(BITS_EVAL2(BITS_EVAL2(__VA_ARGS__)))
#define BITS_EVAL2(...) __VA_ARGS__
#define BITS(bit, ...) ((1 << bit) | BITS_EVAL(BITS(__VA_ARGS__)))
Вышеуказанное не работает. Что в настоящее время он делает:
// BITS(2,5,7) --> ((1 << 2) | BITS(5, 7))
Однако то, что я хотел бы достичь, это один из них (или эквивалента):
// BITS(2,5,7) --> ((1 << 2) | (1 << 5) | (1 << 7))
// BITS(2,5,7) --> ((1 << 2) | ((1 << 5) | ((1 << 7))))
Может кто-нибудь помочь мне с моими поисками, или скажите мне, что это невозможно достичь этого?
Вы не должны использовать имена, начинающиеся с подчеркивания, поскольку они [зарезервированы] (http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html). – e0k
@ e0k Вы настроены правильно. Я назвал его '_BITS' совместимым с макросом' _BV' из avr-libc и потому, что он будет в моей собственной «частной библиотеке». – Fritz
'(1 << bit) ' -->>' (1u << бит) '. Это помогает. Иногда. – wildplasser