宏的二次展开

摘要:
原文:单击打开链接对象的宏(如宏)和不带参数的函数宏(如函数宏),或宏体中带有#(字符串化)或##(粘贴)的宏,并仅执行扫描(simplescan)。否则,将执行两次扫描。扫描两次:预扫描:扫描参数并完全扩展可以扩展的参数。Secondscan:使用展开的参数展开宏体,并递归展开展开的结果

原文:点击打开链接

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


免责声明:文章转载自《宏的二次展开》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇以语音评测的PC端demo代码为例,讲解口语评测如何实现Oracle 通过触发器 来创建 同步临时表 及处理 通过 自治事务 来解决 查询 基表的问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

使用nebula把联想个人云存储映射到当前网络使用的方法

整个过程涉及三个主机。一个是家中台式电脑的家庭内网ip为192.168.69.101,另一个是公司的笔记本电脑mac,另一是具有公共ip的服务器。云存储在家中,家在同一个intranet中,IP地址为192.168.69.100。最终的效果是,我可以在mac上直接访问云存储192.168.69.100的smb服务,通过nat渗透,同一个城市可以达到星云下载地...

如何在jenkins上新建一个项目及其简单配置

单击[新建]进入选择页面,您可以在此页面上配置项目(包括拉取源代码、修改连续构建时间以及在打包和部署之前修改配置文件)3。在General中,您可以设置要构建的版本,如下图5所示。在源代码管理模块中,您可以设置源代码地址(我们公司常用的Git)6。如果是自动构建,您可以将自动构建时间(即构建频率)设置为7。以下是构建中的一些设置。您可以使用shell修改源代...

如何在Java应用中提交Spark任务?

我丈夫是一个用户定义的ID,作为参数传递给Spark应用程序;Spark初始化后,可以通过SparkContext_ ID和URL通过驱动程序连接到数据库,新版本关联关系的插入归因于互联网时代的信息爆炸。我看到了群友的聊天,了解了SparkLauncher。经过调查,我发现它可以基于Java代码自动提交Spark任务。因为SparkLauncher的类引用了...

mysql之排序查询

高级文章目录3:排序查询功能:1.按单个字段排序案例1:查询员工信息,要求工资从高到低排序2.为排序添加筛选条件案例1:部门编号˃=90的员工信息,按员工编号降序排序案例2:部门编号˃=90的人员信息,按输入时间排序。按表达式排序案例1:按年薪显示员工信息和年薪4按别名排序案例1按年薪升序查询员工信息5.按函数(长度)排序案例1查询员工姓名并按姓名长度减少...

wifi密码暴力破解

转自:Python最新暴力破解WiFi,攻破所有密码限制,最强破解!...

Python-正则

,三:量词*重复0次或多次{0,}+重复一次或多次{1,}?重复0或1次{1,0}{n}重复n次{n}{n,}重复n次,或更多次{n,m}将n次重复到m次Escape:如果字符串中有特殊字符要匹配,请在常规字符和字符串前面添加r。如果特殊字符在字符组中,则它们是匹配的特殊字符,但为了记忆,匹配时会转义所有特殊字符。...