【发布时间】:2009-09-15 20:54:02
【问题描述】:
我正在研究微控制器黑客,虽然我对按位运算符和硬件对话非常熟悉,但我发现生成的代码非常冗长和样板。我的高级程序员想要找到一种有效但有效的方法来清理它。
例如,寄存器中有很多设置标志:
/* Provided by the compiler */
#define SPIE 7
#define SPE 6
#define DORD 5
#define MSTR 5
#define CPOL 4
#define CPHA 3
void init_spi() {
SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);
}
幸好有隐藏实际端口 IO 操作的宏(左侧),所以它看起来像一个简单的分配。但对我来说,所有这些语法都很混乱。
要求是:
- 它只需要处理最多 8 位,
- 位位置必须能够以任意顺序传递,并且
- 应该只需要传递设置位。
我想要的语法是:
SPCR = 位(SPE、SPIE、MSTR、SPI2X);
到目前为止,我想出的最好的是一个组合宏/功能:
#define bits(...) __pack_bits(__VA_ARGS__, -1)
uint8_t __pack_bits(uint8_t bit, ...) {
uint8_t result = 0;
va_list args;
va_start(args, bit);
result |= (uint8_t) (1 << bit);
for (;;) {
bit = (uint8_t) va_arg(args, int);
if (bit > 7)
break;
result |= (uint8_t) (1 << bit);
}
}
这在我的特定架构上编译为 32 个字节,执行需要 61-345 个周期(取决于传递了多少位)。
理想情况下,这应该在预处理器中完成,因为结果是一个常数,并且输出的机器指令应该只是将一个 8 位值分配给一个寄存器。
这可以做得更好吗?
【问题讨论】:
标签: c macros bit-manipulation c-preprocessor