宏的二次展开

原文:点击打开链接

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)//这里的宏体展开怎么会是这样呢?看到这的高手们可以给我解下惑哈!


原文地址:https://www.cnblogs.com/lulululu/p/3693835.html