今天试了一下C/C++混合编程,然后就出现了上面那个蛋疼的问题,去网上查了一下,发现原来是C语言和C++预编译头的问题。
error:预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)
英文版: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)
或者fatal error C1853: ‘xxx.pch‘ is not a precompiled header file created with this compiler.
这个问题是在VS项目中同时有.c和.cpp文件时,编译器会对它们采用不同的编译方式(主要因为函数声明的处理方式不同,C语言没有多态,函数名编译后比较正常,而C++有多态的特性,所以编译之后函数名面目全非)。
那么预编译头是什么鬼?下面抄自百度百科:
所谓预编译头,就是把头文件事先编译成一种二进制的中间格式,。预编译头物理上与通常的.obj文件是一样的,但是千万不要把这个中间格式与. o/.obj/.a/.lib的格式混淆,他们是截然不同的!所以预编译头文件的特性和目标文件也不同(尽管他们都属于某种中间文件)。编译入预编译头的.h,.c,.cpp文件在整个编译过程中,只编译一次,如预编译头所涉及的部分不发生改变的话,在随后的编译过程中此部分不重新进行编译。进而大大提高编译速度,并便于对头文件进行管理,也有助于杜绝重复包含问题。——但也有类似的地方的,比如,它们都是编译器之间不兼容的^_^,就是说你不能把VC生成的预编译头拿到GCC上去用。甚至扩展名都不一样,VC的是大家都熟悉的.
pch,而GCC的,是.gch。
那么什么时候要用预编译头?下面还是抄自百度百科:
1)当大多.c或.cpp文件都需要相同的头文件时。
2)当某些代码被大量重复使用时。
3) 当导入某些不同库都有实现的函数,并产生混乱时。
那么,上面的问题主要就是因为C语言和C++的预编译头不同,VS默认使用的是C++的预编译头,而C语言需要其他类型的预编译头,没法顾全二者的话。
三种解决方案:
1.最简单粗暴的办法就是整个项目都不使用预编译头。不过强烈不推荐,预编译头可以使编译时间大大减少,因而保留预编译头是很重要的。
2.观察一下,看C语言还是C++的文件多,把少的那种文件的预编译头去掉。这种比较简单。
3.将c文件整个设置为一个项目,编译成dll或者lib动态载入,整个项目使用相同的预编译头。
关于预编译头,有两个几个选项,一个是Yu(使用预编译头),一个是Yc(创建预编译头)创建工程的话,stdafx.cpp的选项是Yc,即创建预编译头,而其他文件的属性均为Yu。
关于预编译头设定的修改方法:
由于这里只有一个c文件,所以就直接把.c文件的属性修改成不使用预编译头了。
关于C/C++混合编程还要注意的一个地方,C++要使用C语言的函数,或者引用C语言的头文件时,需要在前面加上extern "C"关键字。
例如:
C语言的.h文件
#ifndef __CFILE_H_ #define __CFILE_H_ extern int CTest(int a, int b); #endif
.c文件
#include "CFile.h" int CTest(int a, int b) { return a + b; }
cpp文件:
#include "stdafx.h" #include <iostream> using namespace std; extern "C"{ #include "CFile.h" }; int _tmain(int argc, _TCHAR* argv[]) { int a = 1; int b = 2; cout<<CTest(a, b); system("pause"); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。