#define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule))
#define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__))
#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) __VA_ARGS__
#define RULE_PADDING_IDS(r) PAD13_##r, PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r,
0. -> 推导符:因-> 果
1. 符号“#” 表示字符串化
2. 符号“##”表示去空格连接
例子: #define LINK_PARA(x, y) x ## y
LINK_PARA(int, 10) -> int10
3. 可变参数...与__VA_ARGS__
C99标准文档第6.10.3章节宏替换(6.10.3 Macro replacement)中描述如下
The identifier _ _VA_ARGS_ _ shall occur only in the replacement-list of a function-like macro that uses the ellipsis notation in the arguments.
省略号...只能出现在宏参数列表中, __VA_ARGS__出现在替换列表中。...是参数,__VA_ARGS__是实际列表
例子: #define LINK_PARA(x,...) x, __VA_ARGS__ (正确)
#define LINK_PARA(x,__VA_ARGS__ ) x, ... (错误)
C99标准文档第6.10.3.1章节宏替换(6.10.3.1 Argument substitution)中第2小段描述如下
An identifier _ _VA_ARGS_ _ that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it.
__VA_ARGS__被当作一个参数来看,实际上是一个参数列表
宏替换规则:
C99标准文档第6.10.3章节宏替换(6.10.3 Macro replacement)中第11小段描述如下
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
C99标准文档第6.10.3.1章节宏替换(6.10.3.1 Argument substitution)中第1小段描述如下
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.
总结来说:
1.最外层括号中的逗号为实参分隔符,内层的逗号不分隔该层实参(暂时作为一个整体);
2.带有预处理指令#或##的形参,不参与宏替换或宏展开
例如上面知识储备2例子中的宏
实际调用时:LINK_PARA(LINK_PARA(int, 16) , _t)
分析:LINK_PARA(LINK_PARA(int, 16) , _t)
目标宏中最外层的括号内,有一个逗号在_t左边,根据规则1判断:这个逗号是实参分隔符,把LINK_PARA(int, 16) , _t原符号,分割成了LINK_PARA(int, 16) 与 _t两个参数
那么相当于#define LINK_PARA(x, y)中的 x= LINK_PARA(int, 16) , y =_t. 因为x 后面, y前面都有 ##, 根据规则2 停止解析 LINK_PARA(int, 16)y, 这个只是分析结果,结果会报错.
如果改成如下宏:
#define LINK_PARA(x, y) x ## y
#define ADD_LAYER(a, b) LINK_PARA(a, b)
#define EXPAND_MACRO(x, y) ADD_LAYER(x, y)
EXPAND_MACRO(EXPAND_MACRO(int, 16), _t)
分析EXPAND_MACRO(EXPAND_MACRO(int, 16), _t):
1.根据规则1 分解参数如下:
参数 x = EXPAND_MACRO(int, 16),
参数 y = _t
目标结果是:EXPAND_MACRO(