宏#、##、@、__VA_ARGS__基本使用
一、宏解释
1.#用来把参数转换成字符串
2.##:用于将带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串;但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法.
3.__AV_ARGS__表示可变参数列表。
4.##__AV_ARGS__可用在无参数数去除前面的“,”否则当不传参时会报错。
二、使用步骤
例程1:验证“#”转换字符串功能
#include <stdio.h>
#define LOGS(x) printf("%s--%d\r\n",#x,x);
int main()
{
int a=10;
LOGS(a);//测试#(参数转字符串)
return 0;
}
运行结果:
a–10
例程2:验证“##”连接字符串功能
#include <stdio.h>
#define LOG(x) out_##x()
void out_1(void)
{
printf("This is out_1 \r\n");
}
void out_2(void)
{
printf("This is out_2 \r\n");
}
int main()
{
LOG(1) ;//测试## (拼接)
return 0;
}
运行结果:
This is out_1
例程3:样可变参
代码如下(示例):
#include <stdio.h>
#define LOGV(...) printf(__VA_ARGS__);
int main()
{
int a=10,b=11;
LOGV("a=%d--b=%d\r\n",a,b);//测试可变参
return 0;
}
运行结果:
a=10–b=11
例程4:综合应用
#include <stdio.h>
#define LOG(module_str, msg, ...) printf("["module_str"][%s][%d] "msg"", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define INIT_LOG(msg, ...) LOG("init",msg, ##__VA_ARGS__)
int main()
{
int a=10;
INIT_LOG("%d\r\n",a);
return 0;
}
运行结果:
[init][main][7] 10
例程5:验证##VA_ARGS中“##”作用
#include <stdio.h>
#define LOG( msg, ...) printf("[%s][%d] "msg"", __FUNCTION__, __LINE__,##__VA_ARGS__)
int main()
{
int a=10;
LOG("1234\r\n");//去除##VA_ARGS__中的##将会报错
return 0;
}
运行结果:
[main][5] 1234
如果去除##VA_ARGS__中的##将会报错
例程6:验证@符作用
#@x会将x转换为字符 例如#@a等价于’a’;
#include <stdio.h>
#define symbo(x) #@x
int main()
{
char buf=symbo(a);
LOG("buf:%c\r\n",buf);//打印字符a
return 0;
}
运行结果:
buf:a
总结
#define LOGV(...) printf(__VA_ARGS__);
#define LOG( msg, ...) printf("[%s][%d] "msg"", __FUNCTION__, __LINE__,##__VA_ARGS__)
#define LOG( msg, ...) printf("[%s][%d] "msg"", __FUNCTION__, __LINE__,__VA_ARGS__)
第一条宏使用的__VA_ARGS__ 可进行变参 LOGV(“123\r\n”)、LOGV(“%d–%d\r\n”,a,b);这样的语句都可以进行打印。
第二条宏增加了__FUNCTION__及__LINE__宏可在调用时将所调用的函数及行号打印出来。同时一样支持LOGV(“123\r\n”)、LOGV(“%d–%d\r\n”,a,b);所有通用的打印。
第三条宏只支持LOGV(“%d–%d\r\n”,a,b);这样的带参数打印(至少一个参数),否则将会进行报错例如:LOGV(“123\r\n”),正如前面的说明##__ VA_ARGS__可去除前面参数的“,”因此##__ VA_ARGS__去除的不是调用参数的“,”而是宏声明时前面的参数的“,”如__FUNCTION__,__LINE__等。
当然在使用中如果可以把底层的printf两个参数颠倒过来,将__VA_ARGS__放到参数最前面我想应该也能实现使用__VA_ARGS__即可进行打印无参内容。