定义一个宏MAX3,它给出最多三个值。
这就是我提出的:
#define MAX3(a,b,c) ( ((a) > (b)) && ((a) > (c)) ) ? (a) : ((b) > (c)) ? (b) : (c)
这很难读。有没有办法用if-else语句编写等效的宏?
答案 0 :(得分:6)
在标准C99语言中,不能使用带有语句的类似表达式的宏(因为在C99语句和表达式中,语法和语义都有很大差异。)
但是,GCC(以及其他一些受GCC启发的扩展程序的编译器,例如clang)为此提供了一个很好的扩展:statement expressions(文档提供了与您的问题相关的示例)。使用该扩展,您可以编写类似
的代码 #define MAX3(A,B,C) ({ int a=(A); int b=(B); int c=(C); int m; \
if (a>b) m=a; else m=b; \
if (c>m) m=c; \
m; }) /* bad macro */
但是,如果您使用该宏,例如仍然无法工作
int badex(int x, int y) {
int a= x+y; int m= x*y; int d=x-y;
return MAX3(a,m,d);
}
我希望你明白为什么它不会工作(例如在a
内部badex
和a
内部MAX3
宏之间发生冲突。所以你需要一种方法在每次调用宏时都有唯一的名称。同样,GCC为此提供了一个很好的扩展,__COUNTER__
宏(扩展为一个唯一的数字,计数)与预处理器中的concatenation一起使用。
然后您将编写类似
的代码 #define MAX3(A,B,C) MAX3_COUNTED((A),(B),(C),__COUNTER__)
#define MAX3_COUNTED(A,B,C,N) ({ \
int a_##N=(A); int b_##N=(B); int c_##N=(C); \
int m_##N; \
if (a_##N>b_##N) m_##N = a_##N; else m_#N = b_##N; \
if (c_##N>m_##N) m_##N=c_##N; \
m_##N; }) /* better example */
然后第一次调用我们的宏,例如MAX3(i++,j++,k++)
可能会扩展为MAX3_COUNTED((i++),(j++),(k++),1)
,并使用a_1
b_1
扩展为某些内容...以及第二次调用,例如展开MAX3(a,m,d)
MAX3_COUNTED((a),(m),(d),2)
会使用a_2
b_2
等,因此效果会更好。
当然,定义static inline max3(int a, int b, int c)
函数更清晰(特别是因为副作用:您的MAX3
宏会通过MAX3(i++,j++,k++)
之类的调用提供顽皮的效果和结果
关于这一点的一般教训是,你应尽可能避免使用宏(更喜欢内联函数),当你绝对需要宏时,请注意名称冲突和扩展。
使用作为gcc -C -E
调用的GCC向您显示程序的预处理形式。
答案 1 :(得分:3)
这样做可能会更好:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(a, MAX(b, c))
或者更好的是,使用内联函数而不是诉诸旧skool preprocesser滥用:
inline int max3(int a, int, int c) { return max(a, max(b, c)); }
它比宏更健壮,效率更高。