# 和 ## 是功能强大的宏,根据日常使用介绍一下。
# 将宏参数变为字符串,就是在其两边加".
#include <stdio.h>
#define TRACE(X) printf( #X" = %#x\n",X)
int main()
{
int a = 0x10;
int b = 0x20;
TRACE(a);
TRACE(b);
return 0;
}
会打印出:
a = 0x10
b = 0x20
TRACE(a)
#a -> "a"
printf( "a"" = %#x\n",a)
printf( "a = %#x\n",a)
特别说明:挨着的两个字符串会初始化为一个连起来的字符串。
## 将宏参数与其他记号连接成一个记号。它可以多次使用连接多个记号为一个记号。
#define FL(x,y) x##.##y
printf("%d.%d = %f\n",1,99,FL(1,99));
宏展开后为:printf("%d.%d = %f\n",1,99,1.99);
1.99是一个记号,一个浮点数,不是”1.99"字符串。它的输出为:“1.99 = 1.990000”
这个应用比较多,只有一个特别说明:可变参数中,如果##后面参数__VA_ARGS__是空的,##前面的","会被去掉。
#ifdef MY_TRACE
#undef MY_TRACE
#define MY_TRACE(format, ...) \
do \
{ \
printf((format), ##__VA_ARGS__); \
} while (0)
#endif
MY_TRACE("hello!\n");
会得到:
do \
{
printf("hello!\n");\
}while(0);
#和##后面的参数都不进行宏展开,这个是为了防止形成递归的展开循环。
#define PRJ_NAME A10
#define STR(a) #a
puts("project is "STR(PRJ_NAME));
这个打印出的是“project is PRJ_NAME”
要想用宏的内容做参数可以加一级宏,让宏先展开再做#或##的参数。第一级将宏展开,第二级变为字符串。
#define PRJ_NAME A10
#define _STR(a) #a
#define STR(a) _STR(a)
puts("project is "STR(PRJ_NAME));
这个打印出的是“project is A10”