再看C/C++中的宏(Macros)

通常我们对C/C++中宏的理解不外乎两点:

  1. 用来处理头文件的重复包含。
  2. 用来定义类似的函数的宏。

对于第一点,这个大家都能很好理解。第二点:用来定义类似的函数的宏也常常见到,比较经典的是:

define max(a,b) (a>b)?(a):(b)

类似于这样的作法主要是想绕过类型检查,这样无论a和b是什么类型之要能用">"运算符来比较的便可以使用宏来代替反复写max函数不同版本。但这样做明显有一个问题:我们缺少了类型保护,这对于大型应用程序来说是非常恐怖的一件事。(但也不尽然)。
C++中引入了范型(Generic Method)来解决这个问题。

但我今天想表达的全然不是上面这些,C/C++中的宏还有一个用处:代码生成器(Code Generator)

也许你对此不屑,坦白地讲先前我也是如此。这个很明显嘛,上学的时候我都知道了,比如上面的例子,当你写出如下的代码:

int iMax = max(5,6);

编译器会为你“自动”生成代码:

int iMax = (5>6)?(5):(6);

确实如此,编程三年以来,我确实也是这样的理解的。直到最近在看Graham Paul的《ANSI Common Lisp》,前言中有这样一句话:

Macros, for example: Lisp programmers can, and often do, write programs to write their programs for them.

是的,We Can Write a Program to program for us.

经此一提,抽象层次,思考方式转然一变:是呀,我们可以写出一些程序,这些程序的作用是为我们写程序。像绕口令?是有些。

结合经验的话,我觉得VC/MFC的源码中经常会出现这种技术/思想的利用。刚开始我总不能理解为什么MFC的源码中总是会插入一些宏,有些宏还非常巨大。当时也觉得微软的这些程序员让人不可思议。现在我知道了:

对于他们(MFC的作者)来说,他们有时在写程序,有时却在写会帮助他们写程序的程序(宏)。

原来如此!

本篇只做提醒不做更深的介绍,有兴趣的可以:

  1. 看看MFC的源码,找找哪些宏是Generic Method,哪些是Code Generator;
  2. 去看看Graham Paul的《ANSI Common Lisp》;
  3. 如果你足够强,可以看看Graham的《On Lisp》;
@ 2008-12-27 08:00

Comments:

Sharing your thoughts: