这是一个谜语。
想象一下,我有以下C ++函数:
template<uint8_t MASK>
uint8_t Foo(uint8_t val)
{
uint8_t step = 0;
uint8_t result = 0;
if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;}
if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;}
//...etc...
if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;}
return result;
}
当我实例化这个函数时(下面的所有值都只是示例值):
uint8_t someval = Foo<0xAA>(44);
编译器优化了Foo()中的if语句,因为它在编译时知道if()语句的结果是什么。
这很好,但是在C中尝试做同样的事情是有问题的,因为创建了局部变量 step 。
如果 step 不在那里,你可以像这样做一个大的#define:
#define Foo(MASK, val) (\
((MASK & 0x01) ? (val & 0x01) : 0) | \
((MASK & 0x02) ? (val & 0x02) : 0) | \
...etc...
((MASK & 0x80) ? (val & 0x80) : 0) | \
)
但是使用步骤,我有点陷入僵局。如何在C中为C ++模板函数获取与C ++模板相同的功能并使用局部变量?
请注意,使用内联C函数不是一个答案,因为编译器在编译时不会知道 MASK 的值,因此所有比较都不会被优化,因此将成为最终的编译输出。
另请注意,更改#define以包含结果值也不是答案,因为这会更改“函数”签名。
最后,我完全清楚这个谜语可能没有答案。
答案 0 :(得分:5)
让你的宏尝试做模板的工作;创建内联函数 -
#define Foo(MASK, val) inline uint8_t Foo_##MASK(uint8_t val) \
{ \
uint8_t step = 0; \
uint8_t result = 0; \
if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;} \
if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;} \
//...etc...
if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;} \
\
return result;\
}
答案 1 :(得分:2)
如何(GCCism):
#define Foo(MASK, val) ({ \
uint8_t step = 0; \
uint8_t result = 0; \
if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;} \
if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;} \
//...etc...
if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;} \
result;})
答案 2 :(得分:2)
你只是做出错误的假设
请注意,使用内联C函数不是编译器的答案 在编译时不会知道MASK的值,因此所有的 比较将不会被优化,因此将成为其中的一部分 最终编译输出。
我刚刚测试过,gcc能够毫无问题地内联所有内容:
static inline
unsigned Foo(unsigned MASK, unsigned char val)
{
unsigned char step = 0;
unsigned char result = 0;
if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;}
if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;}
//...etc...
if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;}
return result;
}
int main(int argc, char *argv[]) {
return Foo(0x02, argc);
}
导致main
的以下汇编程序:
main:
.LFB1:
.cfi_startproc
andl $2, %edi
movzbl %dil, %eax
ret
.cfi_endproc
.LFE1:
.size main, .-main
和clang功能相同。