宏的二次展开
原文:点击打开链接
object-like宏 和 function-like但没有参数的宏,或macro body 有 #(stringified ) or ##(pasted) 的macro, 只执行一遍扫描(simple scan)。否则就要执行两遍扫描。
两遍扫描:
prescan: 对参数进行扫描,并对可以展开的参数进行完全的宏展开。
second scan: 用展开后的参数,对宏体进行展开,对展开后的结果 递归进行 完全的宏展开。
一遍扫描举例:
object-like宏:
#define no_param hah
no_param ==> hah
function-like宏,含有##:
#define UNAME(a) a##__LINE__
UNAME(lidy) ==> lidy__LINE__
function-like宏,含有#:
#define INC(x) x+1
#define STR(b) #b
STR(INC(x)) ===> "INC(x)"
递归问题
无论是simple scan 或 twice scan的宏展开过程,都不允许对同一宏进行第二次展开。
example:
simple scan:
#define x (4 + y)
#define y (2 * x)
x ==> (4 + y)
==> (4 + (2 * x)) 这里x不进行二次展开
twice scan:
#define a(x) a(x)+1
#define b(x) x+2
b(a(y)) ==>b(a(y)+1) 先对参数进行扫描
==>a(y)+1 +2 a(y)不能 进行第二次展开
同一宏名不允许重复定义
如果两个宏定义基本一致,是不会报错的。意思就是说前面定义了某个宏,后面定义同一名字的宏,除非与前面同名的宏定义一致,否则就是重复定义(即把同一个宏名定义为其它的含义),会报错。
判断宏一致:4条都要满足
1同是object-or function-like
2 宏体中的token要相同(就是空白分割的token)
3 如果有参数,那么形参要相同
4 有相同的空白处(空白字符数不要求一样)
相同定义,不是重复定义,不报错
#define FOUR (2 + 2)
#define FOUR (2 + 2)
#define FOUR (2 /* two */ + 2)
重复定义错误:
#define FOUR (2 + 2)
#define FOUR ( 2+2 ) //第4条 空白处不对
#define FOUR ( 2 + 2) //第4条 空白处不对
#define FOUR (2 * 2) //第3条 宏体的TOKEN不同
#define FOUR(score,and,seven,years,ago) (2 + 2) //第1条不符号
宏调用中重定义那个宏,那么新的定义只在参数展开中起作用,外层宏的宏体展开还是使用原先的定义
#define f(x) x x
f (1
#undef f
#define f 2
f)
==>1 2 1 2
f(2 3) ==> 2(2 3)//这里的宏体展开怎么会是这样呢?看到这的高手们可以给我解下惑哈!