nju-pa摸鱼记3-NEMU中宏的源码阅读
一、前言
有关于如何使用宏定义检测某个宏是否存在在前两篇专栏中已经讨论得差不多了,本篇将目光转回NEMU的代码框架,探讨include/macro.h
中的有关宏的原理。
二、macro.h
NEMU代码框架中的include/macro.h
文件中定义了一些列宏
1 |
|
从注释中可以看出,这些宏都是根据布尔宏(即若被定义则只有可能被定义为0
或1
)是否被定义或者定义为什么值而决定后面变长参数表中的代码在预编译时是否被保留。由于它们的原理是相通的,所以这里只分析宏IFDEF(macro, ...)
,并使用自顶向下的方法,从顶层宏定义一直追踪到最深层的定义。
宏IFDEF(macro, ...)
的第一个参数是一个布尔宏,第二个参数是变长列表,可以传入语句或代码块。若宏macro
被定义则保留代码,反之什么都不保留。在它的顶层定义中使用了宏MUXDEF(macro, a, b)
,它是一个广义的选择器,不管a
和b
的类型是什么。在这里,__KEEP
和__IGNORE
是两个宏函数,它们的定义如下:
1 |
|
它们的功能和它们的名字相同,__KEEP
将保留所有的输入,而__IGNORE
将所有输入舍弃。所以,在这里宏IFDEF
使用宏MUXDEF
选择__KEEP
宏函数或__IGNORE
宏函数中的一个,然后再将选出来的宏函数作用到后面的代码上,决定这段代码的去留。
举个例子:
1 |
|
在上面的例子中,因为宏FOO
已经被定义了,所以再MUXDEF
的作用下,宏函数__KEEP
被选择出来作用在printf
语句上,最后这个语句被保留了下来。
接下来看宏MUXDEF
是怎么实现的:
1 |
|
宏MUXDEF
又调用了宏MUX_MACRO_PROPERTY
,它的作用是使用宏concat
为宏macro
添加一个前缀__P_DEF_
,然后将处理过的宏传给宏MUX_WITH_COMMA
。上一篇所介绍的技术在这里体现了出来:如果布尔宏被定义了,那么加上前缀后将得到__P_DEF_0
或__P_DEF_1
,然后再定义这两个宏,通过逗号控制最后传入CHOOSE2nd
宏的第二个参数为a
,最终选择结果为a
;如果宏没有被定义,那么加上前缀后的宏不会再进行解释,那么“contain_comma a
”部分将作为传入CHOOSE2nd
的第一个参数,最终选择结果为b
。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!