最近在对一段代码进行重构的时候,发现宏 define 能发挥很大作用。关于其在代码重构方面的使用,本文会举一个具体的例子。首先,我们来看一下其高级特性:Stringize (字符串化)及 Token Pasting。
Stringize
ANSI C 允许在字符串中包含宏参数。# 符号用作一个预处理运算符,它可以把语言符号转化成字符串。如下例所示(在 VS 及 GCC 下最终结果均一样):
1 |
|
Token Pasting
## 预运算符可以把两个语言符号组合成单个语言符号。如下例所示(在 VS 及 GCC 下最终结果均一样):
1 |
|
输出:a[1] = 1
我们再来看一个例子(在 VS 可编译成功,在 GCC 下出错):
1 |
|
这个例子在 VS 下可以正确输出结果,但在 GCC 下会输出如下错误提示:
解决这个问题很简单,只需要将第一行代码中的 stru.##mem 中的 ## 去掉即可,即改为:
1 | // 下式对 VS 及 GCC 均适用 |
实际上,对 GCC 而言,在要使用 ## 的地方,如果它的前边已经有运算符(如 . ( ) [ ] ),我们都需要删除掉它,因为这些运算符已经起到它的作用(即起到分割 Token 的作用)。
#、## 在代码重构中的作用
我们先来看一段代码:
1 | request[First_Node_In_The_Network] = ptr->get_request_param(environ, First_Node_In_The_Network, "Get First Node In The Network"); |
很明显这段代码的所有行的结构都是一样的,但这种写法却容易出错,也不方便后续维护,因为我们选择对他进行重构。重构之后的代码如下:
1 |
|
这样一来,代码就清晰很多,而且维护起来也更加方便。我们可以测试一下这个宏是否正确:
1 |
|
输出结果如下:
说明这个宏是正确的。
注:
左中括号 “[” 已经起到分割 Token 的作用,所以,左中括号和 seq 之间不用再加 ##(在 VS 环境中可以加,GCC 环境中不行)
上图中的 “Get “ “First” “ Node In The Network” 其实跟 “Get First Node In The Network” 是等价的