#、##、 …和_ VA_ARGS _
1.#
假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing).简单理解就是:#n把一个宏参数n变成字符串n
#incldue <stdio.h>
#define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))
int main(void)
{
int y =4;
PSQR(y);
PSQR(2+4);
return 0;
}
输出结果:
the square of y is 16.
the square of 2+4 is 36.
第一次调用宏时使用“y”代替#x;第二次调用把2+4转成字符串“2+4”。
2.##
##运算符可以用于类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分。这个运算符把两个语言符号组合成单个语言符号。简单理解就是a##b转化为ab,把a和b连在一起了
例如:
#define XNAME(n) x##n
这样宏调用:
XNAME(4)
展开后:
x4
程序:
#include <stdio.h>
#define XNAME(n) x##n
#define PXN(n) printf("x"#n" = %d\n",x##n)
int main(void)
{
int XNAME(1)=12;//int x1=12;
PXN(1);//printf("x1 = %d\n", x1);
return 0;
}
输出结果:
x1=12
3.可变参数宏 …和_ VA_ARGS _
VA_ARGS 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。
实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ VA_ARGS _就可以被用在替换部分中,替换省略号所代表的字符串。比如:
#define PR(...) printf(__VA_ARGS__)
int main()
{
int wt=1,sp=2;
PR("hello\n");
PR("weight = %d, shipping = %d",wt,sp);
return 0;
}
输出结果:
hello
weight = 1, shipping = 2
省略号只能代替最后面的宏参数。
#define W(x,…,y)错误!
freertos实例:
#define osThreadDef(name, thread, priority, instances, stacksz) \
const osThreadDef_t os_thread_def_##name = \
{ #name, (thread), (priority), (instances), (stacksz)}
上诉宏定义中出现了##和# 符号,其中
##是一个连接符号,用于把参数连在一起;
#是“字符串化”的意思。出现在宏定义中的#是把跟在后面的参数转换成一个字符串。
例如:
#define paster( n ) printf( "token" #n" = %d\n ", token##n )
所以paster(9);就是相当于 printf("token 9 = %d\n",token9);
那么osThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128);等价于下面的定义
#defineosThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128) \
const osThreadDef_t os_thread_def_Task_LED1 = { Task_LED1,Func_LED1,osPriorityNormal, 0, 128}
linux驱动实例:
module_platform_driver(axi_i2s_driver);
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
那么对module_platform_driver(axi_i2s_driver);进行第一步展开,即:
module_driver(axi_i2s_driver, platform_driver_register,platform_driver_unregister)
继续展开下一层,…并没有实际参数,对应的需要删除##VA_ARGS即:
#define module_driver(axi_i2s_driver, platform_driver_register,platform_driver_unregister) \
static int __init axi_i2s_driver_init(void) \
{ \
return platform_driver_register(&(axi_i2s_driver) ); \
} \
module_init(axi_i2s_driver_init); \
static void __exit axi_i2s_driver_exit(void) \
{ \
platform_driver_unregister(&(axi_i2s_driver) ); \
} \
module_exit(axi_i2s_driver_exit);
module_platform_driver()宏的作用就是定义指定名称的平台设备驱动注册函数和平台设备驱动注销函数,并且在函数体内分别通过platform_driver_register()函数和platform_driver_unregister()函数注册和注销该平台设备驱动。