在预编译阶段,编译器只是完成对于预处理指令的语法检查以及字符串常量的替换。也就是说在该阶段编译器并不做变量、函数等的语法检查。 可以写个简单的实验程序。

#include <stdio.h>
#define IRESULT xxxxx
typede int  IRESULT;
xxxxx main()
{
   printf("%d\n", sizeof(xxxxx));
}

此处typedef故意写错成typede。保存程序,用命令:

cc -E test.c > file

进行预编译,结果重定向到file文件中。没有错误提示,#include所指示的源文件在开头进行了展开,#define的内容也在全文中做了替换,此阶段编译器对于 typede明显的语法错误只字未提,也验证了开头之说。另外#define的替换范围是从定义处往后的所有需要替换的行。其他预处理指令也类似。 当然,如果是预处理指令拼写错误,编译器在用-E编译阶段是必然要发出错误的抱怨。如将#define 写错成#defin。

过了预处理阶段,#开头的所有行都已经完成了任务,接下来是编译阶段对变量,函数,流程控制,表达式等进行全面的语法检查。此时会发现typede的拼写错误。

此处要说的其实还不够准确,因为看之前的述说好像是为了讲解这两者的区别而故意造的例子,很多人会认为实际编程中谁会写这样的例子。其实,自己不会明知故犯,自找麻烦,有时是迫不得已的。因为,如果有两个头文件中同时出现了这个IRESULT标识符,而这两个头文件不能改动且需要包含在同一个源文件中时,之前的阐述就有参考价值了。 因为typedef只是重命名类型,所以你只要找到头文件看看该定义原型,然后将需要用到IRESULT声明类型的地方进行替换即可。但是顺序需要注意。 最好将宏定义的那个头文件放在最后,至少也应该放在用typedef定义的头文件之后。 最好需要记住的是,两者是在不同阶段处理的所以对于重名上没有标识符重名那么简单。或者说这两者之间的重名本就不该称之为重名,因为两者是在不同的时间段起作用的。