我有以下宏来接受一个陈述并将其相乘
#define X2(s) do { s; s; } while (0)
#define X3(s) do { s; s; s; } while (0)
#define X4(s) do { s; s; s; s; } while (0)
#define X5(s) do { s; s; s; s; s; } while (0)
#define X6(s) do { s; s; s; s; s; s; } while (0)
etc.
所以预处理器扩展
X2(i++)
到
do { i++; i++; } while (0)
我想要一个宏
#define CODE_MULTIPLIER(x,s)
扩展声明s
,x
次。所以
CODE_MULTIPLIER(3,j--)
将扩展为
do { j--; j--; j--; } while (0)
我提出的丑陋想法是:
#define CODE_MULTIPLIER(x,s) do { \
if ((x) == 1) { s; } \
else if ((x) == 2) { s; s; } \
else if ((x) == 3) { s; s; s; } \
else if ((x) == 4) { s; s; s; s; } \
else if ((x) == 5) { s; s; s; s; s; } \
etc. \
else assert(0); \
} while (0)
希望编译器能够优化if
s
为什么你会想要这样的宏? 一个原因(但不是唯一的原因)是嵌入式编程中需要精确延迟。使用while / for循环稍微改变时间。循环的编译器优化可能无法保留精密的时序要求。
以下是一个典型的用法示例:
#define CLOCK_FREQ_Hz (16000000L)
#define US_TO_NOPS(us) ((us) * CLOCK_FREQ_Hz / 1000000L)
#define OFF_ON_DELAY_US (4) // units: microseconds
#define ON_OFF_DELAY_US (2) // units: microseconds
#define OFF_ON_DELAY_NOPS US_TO_NOPS(OFF_ON_DELAY_US) // units: instructions
#define ON_OFF_DELAY_NOPS US_TO_NOPS(ON_OFF_DELAY_US) // units: instructions
PIN = OFF;
CODE_MULTIPLIER(OFF_ON_DELAY_NOPS,asm("nop")); // 4us delay
PIN = ON;
CODE_MULTIPLIER(ON_OFF_DELAY_NOPS,asm("nop")); // 2us delay
PIN = OFF;
我很感激有关如何创建此宏的任何建议。高度偏好独立于编译器的宏巫术(我们的嵌入式家伙并不总是有使用GCC的奢侈品)
感谢名单
答案 0 :(得分:1)
是的,如果你不做太多的事情,这样的事情是可能的。 P99有一整套宏来完成不同类型的这种展开。这里很容易就是
#define toto(I) f(I)
P99_UNROLL(toto, 3); // => f(0); f(1); f(2);
但请注意,对于使用P99,您需要一个能够实现符合C99标准的预处理器的编译器。
答案 1 :(得分:1)
由于递归通常不能在宏中使用,并且您可能没有“扩展展开功能”,因此获得“始终有效的解决方案”的唯一方法是执行一些手动操作,如下所示:
#define X1(s) do { s;} while (0)
#define X2(s) do { s; s; } while (0)
#define X3(s) do { s; s; s; } while (0)
#define X4(s) do { s; s; s; s; } while (0)
#define X5(s) do { s; s; s; s; s; } while (0)
#define X6(s) do { s; s; s; s; s; s; } while (0)
#define CODE_MULTIPLIER(s, i) X##i(s)
您只需在代码中使用CODE_MULTIPLIER(s, i)
即可。这样就可以避免使用if / else if条件表达式。例如,您将使用CODE_MULTIPLIER(i++,3)
。
如果你不打算使用X1,X2 ......可以应用另一个技巧....但只有CODE_MULTIPLIER(s,i):
#define X1(s) s
#define X2(s) s; X1(s)
#define X3(s) s; X2(s)
#define X4(s) s; X3(s)
#define X5(s) s; X4(s)
#define X6(s) s; X5(s)
#define CODE_MULTIPLIER(s, i) do { X##i(s); } while (0)
有一个更好的sintax。