首页 > 代码库 > 【编程拾遗】预编译头文件来自编译器的早期版本

【编程拾遗】预编译头文件来自编译器的早期版本

背景

在一个MFC ActiveX的项目工程中用到了zlib相关的文件压缩程序,这些程序是c语言编写的,在用vs2012编译时提示一下错误:
预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)
特查找解决方法,记录下来。

解决办法

当 Visual C++ 项目启用了预编译头 (Precompiled header) 功能时,如果项目中同时混合有 .c 和 .cpp 源文件,则可能收到 C1853 编译器错误:fatal error C1853: ‘pjtname.pch‘ precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)(致命错误C1853: “filename.pch”预编译头文件来自编译器的早期版本,或者预编译头为C++ 而在C 中使用它(或相反))。

原因
错误是因为当项目中混合了 .cpp 和 .c 文件时,编译器会对它们采取不同的编译方式(主要是因为对函数声明的处理方式不同),因而不能共用一个预编译头文件。在 VC++ 中,默认的预编译头文件是针对 C++ 的 (stdafx.h 和 stdafx.cpp),当然也可以创建针对 C 的预编译头。

解决方法一

对这个问题往往都是建议对整个项目取消预编译头的设置,这显然不是一个好的解决方案。对于一个比较大的工程来说,使用预编译头可以使总的编译时间大大减少。因而保留预编译头的设置才是比较好的解决方案。
适用于绝大多数文件是 .cpp 或绝大多数文件是.c的情况。在这种情况下,将少数的不同类文件设为不使用预编译头是比较平衡的做法,方法是:右键c文件选择属性,在属性页中的C/C++的预编译头选项中,选择不使用预编译头(如果需要设置多个文件,则可以按住 Ctrl 键再同时选中这些文件并设置)。

技术分享

解决方法二

影响的文件比较多,则把它们都设置禁止预编译头的话仍然会使项目总体的编译速度大大降低,得不偿失。这时考虑可以为这组文件建立专用的预编译头。在这种情况下,我们可以在solution中建立一个新的静态链接库(Static Library)工程,将所有的 .c 文件独立出来加入到该工程中单独编译,这样就可以在该静态链接库中针对 .c 文件创建预编译头。但是这样做在一定程度上需要被独立出来的代码在逻辑上是属于同一模块中的,这样才便于维护。不过从设计的角度来说,这个要求一般是满足的,否则就应考虑下项目的总体设计了。

C和C++的类型转换

C++在类型转换上较C的语法规范上要更加严格一些,有时在C程序中编译通过的代码在C++编译器中会检查出错,所以在编译出错的地方要强制进行类型转换。
还有一点,在赋值操作中,左值为const类型,右值为非const变量,这时会自动转换为const类型,反之不行。

转载请注明作者Jason Ding及其出处
Github博客主页(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

【编程拾遗】预编译头文件来自编译器的早期版本