在定义预处理器语句中使用括号

所以我想知道什么时候使用

#define xxx (yyy) 

VS

  #define xxx yyy 

我的项目包含一个在AD0_ADMD_CT上有自己定义的文件,如果我想重新定义它们,我需要在定义中使用(AD0_ADMD_CT)或AD0_ADMD_CT吗?

AD0_ADMD_CT定义为

  #define AD1_ADMD_CT (IO_AD1.ADMD.bit.CT) 

所以它也是

 #define AD0_COMPARETIME (AD0_ADMD_CT) 

要么

 #define AD0_COMPARETIME AD0_ADMD_CT 

两者都没有区别。 在第一种情况下, XXXyyy取代,而(yyy)则是第二种情况。 使用包围的惯例是避免可能发生的逻辑错误。 例如,您将添加function定义为:

 #define f(N) N+N int a = f(5)*f(5) 

预期值为10 * 10 = 100,但输出为35,因为在编译时变为

int a = 5+5*5+5,因此使用运算符首选项规则,输出更改。

所以括号避免了这些类型的错误。

通过添加括号,您强制在括号内的参数在宏体的其余部分之前进行求值,所以如果你有

 #define MULT(x, y) (x) * (y) // now MULT(3 + 2, 4 + 2) will expand to (3 + 2) * (4 + 2) 

除非你的宏有更多,否则它似乎不会影响你当前的情况。

如果您的宏中有运算符,这一点非常重要。 例如:

 #define ADD(x,y) x + y ADD(1,2) * 3 /* Should be 9, is 7 */ 

应该:

 #define ADD(x,y) (x + y) ADD(1,2) * 3 /* 7 */ 

这些优先级问题也适用于@Gi Joe所说的参数,并且需要包含在parens中以获得优先级。

但是,对于像这样的宏:

 #define MAGICNUM 3 

没关系。

要记住的一件重要事情是预处理器只是扩展宏。 例如,如果您有以下行:

 #define AD0_COMPARETIME_1 (AD0_ADMD_CT) #define AD0_COMPARETIME_2 AD0_ADMD_CT num_1 = AD0_COMPARETIME_1; num_2 = AD0_COMPARETIME_2; 

在第一次扩展之后你会有这个:

 num_1 = (AD0_ADMD_CT); num_2 = AD0_ADMD_CT; 

在第二次扩展之后你会有这个:

 num_1 = ((IO_AD1.ADMD.bit.CT)); num_2 = (IO_AD1.ADMD.bit.CT); 

当扩展表达式时,如其他答案中所述,可能出现问题。