С макросом оказалось всё немного сложнее.
При введении в него промежуточной переменной tmp появилась необходимость указывать её тип. Он должен совпадать с типом reg. А т.к. он в общем случае разный и заранее неизвестный, то придётся его вводить одним из параметров макроса.
Как-то так
Код
// Макрос записи в регистр reg битовой последовательности val
// в позицию pos (по младшему разряду), msk - маска битового поля
#define TuneBitField(typename,reg,val,pos,msk) \
do { \
typename tmp=reg; \
tmp |= (((val) << (pos))&(msk)); \
tmp &= (((val) << (pos))|~(msk)); \
reg=tmp; \
} while (0)
В С++ этот макрос можно (а скорее нужно) переоформить в виде шаблонной подставляемой (inline) функции, где параметром шаблона как раз и будет имя типа регистра reg, а аргументом функции будет ссылка на регистр, чтобы его содержимое можно было изменить.
Второй вариант выхода из ситуации (для Си без плюсов) - переписать макрос без использования промежуточной переменной, приведя его к виду: do {reg=(reg&msk1)|msk2;} while (0)
Код
// Макрос записи в регистр reg битовой последовательности val
// в позицию pos (по младшему разряду), msk - маска битового поля
#define TuneBitField(reg,val,pos,msk) \
do { \
reg = ((reg)&(((val) << (pos)))|~(msk))|(((val) << (pos))&(msk)); \
} while (0)