在嵌入式的交叉编译过程中,经常会用到宏定义控制程序运行模式,或者控制打印模式,提高程序开发和调试效率,比如在某个项目中,设置了几种程序运行模式,控制打印输出:
#define MY_PRINTF_NORMAL 0
#define MY_PRINTF_MUST 1
#define MY_PRINTF_ERROR 2
#define MY_PRINTF_DEBUG 3
//#define MY_PRINTF_LEVEL MY_PRINTF_ERROR
#define MY_PRINTF_LEVEL MY_PRINTF_DEBUG
#define myPrintf(level,format, ...); \
do{ \
if(level <= MY_PRINTF_LEVEL){ \
if(level == MY_PRINTF_NORMAL){ \
os_printf(""format"",##__VA_ARGS__); \
} \
else{ \
os_printf("Level:%d:"format"",level,##__VA_ARGS__); \
} \
} \
}while(0);
#endif
其中涉及到了变参函数(形参数量可变的函数)。
1) 变参函数的实现:
将函数宏的形参列表最后的参数用省略号(...)表示即实现了变参函数。__VA_ARGS__用于在宏替换部分中,表明省略号代表什么。
例如:#define PR(...) printf(__VA_ARGS__);
#include
#define PR(...) printf(__VA__ARGS__); //Note:需编译器支持__VA__ARGS__
int main(void)
{
int age = 26;
int weight = 75;
float BMI = 26.4;
PR("oh mashuai");
PR("Age:%d, weight:%d,BMI:%d",age,weight,BMI);
}
2)##__VA_ARGS__ 宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错。
一般这个用在调试信息上多一点
************************************************************ 知识扩展 ****************************************************************************
1) # : 表示将参数转换为字符串输出:
#include
#define P(A) printf("%s:%d.\r\n",#A,A);
int main()
{
int a=1;
int b=2;
P(a);
P(b);
}
运行结果为:
a:1
b:2
2)## : ##运算符可用于类函数宏的替换部分,也可以用于对象宏的替换部分。主要用于将两个语言符号组成单个语言符号,为宏扩展提供一种连接实际变元的手段;
#include
#define XNAME(n) X##n //将定元X和变元n组合,列出X1, X2, X3 ...
#define PRINT_XN printf("X"#n"=%d\n",X##n);
int main(void)
{
int XNAME(1)=10;
int XNAME(2)=20;
int X3=30;
PRINT_XN(1);
PRINT_XN(2);
PRINT_XN(3);
}
程序输出为:
X1=10;
X2=20;
X3=30;