C语言:在VS环境下因#include *.c/.cpp所产生的LNK2005及LNK1169错误及解决办法

C语言:在VS环境下因#include<*.c/.cpp>所产生的LNK2005及LNK1169错误及解决办法

前言(可跳过)

今天在编写某个数据处理程序时,因为代码行数过多影响阅读和编写,所以想将一部分基础处理函数移至另一文件中。理想很丰满,现实很骨感,我将部分函数从a.cpp(化名)移至b.cpp(化名),然后在a.cpp的开头加上#include<b.cpp>,以及相应的extern 函数名(变量);后,进行调试,就立刻出错了,分别是LNK2005及LNK1169。检查了半天,根本就没有发现什么错误,也没有变量重复定义,真是坑人。

问题描述

在文件引用中含有#include<.cpp或者.c文件>,并且被引用文件中含有函数。编译器在链接时产生LNK2005及LNK1169错误,某函数已经在*.obj中定义以及找到一个或多个多重定义的符号。

程序部分情况:
直接引用(包含).c或.cpp文件
情况1
且两者处于同一项目内(废话)
清况2
且被包含文件中有函数
情况3
编译器错误部分情况:
LNK1169LNK2005

代替办法(可跳过)

不用再各个文件里找有没有重复定义的变量或者函数了,没有的,从你直接引用含有函数的.cpp或者.c文件开始,错误就已经注定了。我先介绍几个比较方便(low)的代替解决办法,如果想直接查阅有效的解决方法的读者可以跳过这两个办法。

合并法

很简单,直接把要包含文件的代码复制过来,代替#include<.cpp或者.c文件>原来所在位置就可以了,对了,记得要把被包含文件给删除了(或者从解决方案中移除)
合并结果
调试通过了,是不是很神奇。
这是一个简单的验证是否存在重复声明或者定义的方法,如果你在执行该步骤后的代码仍然存在LNK2005及LNK1169错误,那就说明你的代码的确存在重复声明或者定义,否则,不存在重复的问题。 总不可能原本存在重复,合并成一个文件后重复就不存在了吧,所以这说明不是重复声明或定义的问题。

排除法

这个办法更简单了,直接把被包含文件从解决方案中移除,但是#include<.cpp或者.c文件>不要变,而且文件也不要移动,就像这样:
排除结果
排除结果2
调试也同样能通过:
排除结果3
是不是很神奇?就是在编程的时候不能在同一个资源管理窗口内打开另一个文件有点麻烦。

问题分析

在经过上述两个测试后,我们注意到,问题的由来与两个文件在同一解决方案中有关。而且两个文件的代码放在在同一文件中时,编译链接不会产生错误。所以错误与#include<.cpp/.c>处理有关,而与代码本身实现的功能无关。
在C语言中,#include<.cpp/.c>会将指定文件嵌入源文件中, 也就是相当于我们的合并法。然而,VS在编译时,会将解决方案中的每个.cpp或.c文件进行单独编译,只有.h文件不会。在编译成.obj文件后,VS再将所有.obj文件链接到一起生成.exe文件。所以,如果在a.cpp中直接引用b.cpp的话,在编译后,就会产生包含a+b内容的a.obj和包含b内容的b.obj。 此时VS再进行链接,就会发现a.obj文件中包含有与b.obj重复的函数定义(或变量定义),因此产生LNK2005及LNK1169错误。

解决方法

解决方法就是采用extern关键字,提示编译器遇到此变量或函数时,在其它文件中寻找其定义。而不是直接采用#include<.cpp/.c>,如在a.c中加入b.c函数的声明:如下所示:

extern bool Output_Structure(struct person* n);
extern long Get_File_Size(FILE* File);

那么在a.c中就可以直接使用这些函数了,如果是多个文件需要使用,可以将声明代码放入头文件中,这样只需要引用头文件即可。
解决2

如图所示,编译链接成功。

解决1

总结与反思

应该设计一种编译时插入过的文件不再编译的机制,但其实我没什么会做的,总感觉这种解决方法导致代码长度比之前还要长了,对程序的性能有严重影响。这个解决方法还存在许多缺陷。 希望各位读者如果有更好的办法能在下方留言指点,我会在方便的时候回复的,谢谢大家。
注意:根据来自流沙的刺客反应相同问题的博文,VS6.0下也存在该问题,而我是在VS2019环境下产生的错误,故可以认为在整个VS环境下该错误是普遍存在的。
注意:经实际测试,#include<.c>文件也会产生相同错误,也可用同样方法解决,故认为该错误在C/C++语言中均会出现,且解决方法相同。
C语言下

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值