今天一个同学遇到一个很有意思的问题,也算是比较常见的问题,VS2010编译的时候出现了LNK1169。
简单复述下代码情况:
a.c //函数文件
b.c //主函数,包含了a.c
编译时就出现LNK1169错误。
但是把a.c文件名改成a.h后则编译通过,运行正常。
按道理编译器在预处理时会简单替换#include包含的文件,照此推断不同文件名不会造成任何差异。
尝试用gcc编译b.c,直接通过,运行正常。
于是怀疑是VS2010的问题,可能悄悄做了一些我们不知道的事情。
用cl编译b.c,直接通过,运行正常。
最后查看项目的.vcxproj和.vcxproj.filters终于发现问题,原来VS对.h和.c是区别对待的:
.c文件始终会被编译成目标文件的,即obj文件,.h文件不会被编译。
生成的目标文件最后全部都会被链接。
解析一下整个VS2010编译过程:
先是预处理,b.c中的语句被替换成a.c;
编译a.c和b.c成目标文件a.obj和b.obj;(此时在b.obj中已经包含了a.c中函数的声明定义)
链接a.obj和b.obj。(LNK1169)
也不能说VS做得有问题,因为包含.c文件其实是不编码原则的。如果严格执行声明、定义分离原则,即写成.h和.c形式,使用VS编译是也不会出现这种问题。
总的来说,使用IDE做项目也要去了解编译器背后到底做了些什么,不管是对错误解决还是性能优化都有帮助。
突然感觉makefile好亲切。(>_<)