2014-09-24 64 views
3

我想实现这样的事情:阵列中的#define

#define MACRO(x) {PORTB=0,PORTC=0,PORTD=0} 

MACRO(0); //This would get replaced by PORTB=0; 
MACRO(1); //PORTC=0; 
MACRO(2); //PORTD=0; 

我想创建一个“宏阵列”。我会传入一个索引,它会返回正确的代码。

这可能吗?

编辑:

如果有帮助,PORTB,PORTC和PORTD都是#define语句。

回答

5

它可以通过预处理器来完成,但它可以说是丑陋的。

#define MACRO_CASE0 PORTB = 0 
#define MACRO_CASE1 PORTC = 0 
#define MACRO_CASE2 PORTD = 0 

#define MACRO(X) MACRO_CASE##X 

也看看Boost.Preprocessor库。 (它适用于C和C++)。

更新:后与Jonathan Leffler讨论(见下文),我觉得有义务更新为新的C程序员规劝答案不要滥用(强大的,但脏)技术如上所示。

如果你 - 作为OP要求 - 想要传递给它的索引,它将返回正确的代码,那么你需要求助于预处理器编程。然而,如果你想要做的是执行基于某些条件的不同代码,并且如果条件是编译时常量,那么希望它没有运行时间开销,那么以下方法不仅更清洁,而且更多灵活,因为它也允许传递运行时间值。现在

/* '#include' this definition in any file where you want to use it. */ 
static inline void 
do_the_right_thing(const int selector) 
{ 
    switch (selector) 
    { 
    case 0: 
     PORTB = 0; 
     break; 
    case 1: 
     PORTC = 0; 
     break; 
    case 2: 
     PORTD = 0; 
     break; 
    default: 
     assert(!"cannot do the right thing: invalid selector"); 
    } 
} 

,在你的代码,如果你写

do_the_right_thing(1); /* selector is a compile-time constant */ 

一个体面的编译器优化适当启用相比,使用宏将产生的开销。但是,你也可以写

do_the_right_thing(rand() % 3); /* selector is a run-time expression */ 

,编译器会插入一些快速切换代码选择在运行时适当的操作。

+0

+1:与我的[答](http://stackoverflow.com/a/26019383/15168)相比,这有一个优点,它只能用于整数常量的参数;它也有缺点。 – 2014-09-24 14:32:29

+0

@JonathanLeffler真的,但谁会想用一个整数索引一个数组?如果你想,你也可以使用符号名称。 – 5gon12eder 2014-09-24 14:34:43

+0

这取决于你是否想要动态选择索引:'if(i> = 0 && i <= 2)MACRO(i);'或者类似的东西。如果它是一个微控制器,我怀疑你不想要那个,但是在代码中我看不到'MACRO(1);'比'PORTC = 0'更清晰 - 实际上它少了很多对我清楚。但是,这可能部分地成为问题的假象。如果宏背后的代码是选择PORTB,PORTC或PORTD中的一个用于赋值的LHS(因此用法是“MACRO(1)= 0”),那么我建议不起作用 - 正如我的'不扩展或概括'评论。 – 2014-09-24 14:41:38

3

这将做任务,但它并没有延长或概括很优雅:

#define MACRO(x) (((x) == 0) ? PORTB=0 : ((x) == 1) ? PORTC=0 : PORTD=0) 
+0

...并且效率不高(OP代码看起来像某些微控制器的代码)。 – 2014-09-24 14:25:19

+0

@MichaelWalz:什么是低效?这是问题中显示的示例的编译时常量。首先这不是一个好主意,但它确实按照要求做了什么。 – 2014-09-24 14:26:43

+0

实际上,它**效率很高,因为编译器会优化所有内容。宏MACRO(0)的预处理器输出是(((0)== 0)?B = 0:((0)== 1)?C = 0:D = 0);' – 2014-09-24 14:40:14