Error LNK2005 从敌人到朋友

时间:2021-10-08 10:31:25

本人在写学生信息管理系统时遇到一个很头疼的错误——error LNK2005重复定义错误,苦思冥想百度谷歌bing之后都没能解决问题,于一清早刹那间觉得知道问题出在哪儿了,于是乎起床、开机、修改代码一气呵成,终于0 error(s)\0 warning(s)。

Error LNK2005 从敌人到朋友 

error LNK2005错误分为好几种,我以下分析的是重复定义外部函数,如果是因为重复定义全局变量、头文件的重复包含、或者使用第三方库原因导致的error LNK2005请移步http://www.cnblogs.com/MuyouSome/p/3332699.html

一:问题描述

我的系统分为3个文件(stuheader.h、stufun.c、stuims.c)

  • stuheader.h:该文件中包含头文件、结构体定义以及函数声明等;
  • stufun.c:该文件是系统中除main函数外的其他自定义函数的实现和相互调用;
  • stuims.c:该文件是主函数main调用其他函数组装的整个软件系统。
#include<stdio.h>                            //I/O函数
#include<stdlib.h> //标准库函数
#include<string.h> //字符串函数
#include<ctype.h> //字符操作函数
#define M 50 //定义常数表示记录数 typedef struct
{
char no[]; //学号
char name[]; //姓名
char sex[]; //性别
int age; //年龄
}STUDENTS; //以下是函数原型
int menu_select(); //主菜单函数
int enter(STUDENTS t[]); //输入记录
void list(STUDENTS t[],int n); //显示记录
void search(STUDENTS t[],int n); //按姓名查找显示记录
int del(STUDENTS t[],int n); //删除记录
int add(STUDENTS t[],int n); //插入记录
void save(STUDENTS t[],int n); //记录保存为文件
int load(STUDENTS t[]); //从文件中读记录
void display(STUDENTS t[],int n); //按序号查找显示记录
void sort(STUDENTS t[],int n); //按姓名排序
void copy(); //文件复制
void print(STUDENTS temp); //显示单条记录
int find_name(STUDENTS t[],int n,char *s); //按姓名查找函数
int find_no(STUDENTS t[],int n,char *no); //按学号查找
void modify(STUDENTS t[],int n); //修改记录

stuheader.h代码

#include "stuheader.h"
//菜单函数,返回值为整数,代表所选的菜单项
int menu_select()
{
} int enter(STUDENTS t[])
{
} //显示记录,参数为记录数组和记录条数
void list(STUDENTS t[],int n)
{
} //查找记录
void search(STUDENTS t[],int n)
{
} //删除函数,参数为记录数组和记录条数
static int del(STUDENTS t[],int n)
{
return ;
} //插入记录函数,参数为结构体数组和记录数
int add(STUDENTS t[],int n)
{
return ;
} //保存函数,参数为结构体数组和记录数
void save(STUDENTS t[],int n)
{
} //读入函数,参数为结构体数组
int load(STUDENTS t[])
{
return ;
} //按序号显示记录函数
void display(STUDENTS t[],int n)
{
} //按姓名排序函数
void sort(STUDENTS t[],int n)
{
} //复制文件
void copy()
{
} //显示指定的一条记录
void print(STUDENTS temp)
{
} //按姓名查找函数,参数为记录数组和记录条数以及姓名s
int find_name(STUDENTS t[],int n,char *s)
{
return ;
} //按学号查找函数,参数为记录数组和记录条数以及学号no
int find_no(STUDENTS t[],int n,char *no)
{
return ;
} //修改函数,按照输入学号修改
void modify(STUDENTS t[],int n)
{
}

stufun.c 代码(其中函数体已省略)

 stuims.c 文件中代码如下:

#include "stufun.c"        //stufun.c中已经包含了stufun.h
void main()
{
STUDENTS stu[M]; //定义结构体数组
int length; //保存记录长度
for(;;) //无限循环
{
system("cls"); switch(menu_select())
{
case :length=enter(stu);break; //输入记录
case :list(stu,length);break; //显示全部记录
case :search(stu,length);break; //按姓名查找记录
case :length=del(stu,length);break;//按姓名删除记录
case :modify(stu,length);break; //按学号修改记录
case :length=add(stu,length);break;//插入记录
case :save(stu,length);break; //保存文件
case :length=load(stu);break; //加载文件到内存
case :display(stu,length);break; //按序号显示记录
case :sort(stu,length);break; //按姓名排序
case :copy();break; //复制文件到目标文件
case :exit(); //程序结束
}
printf("按回车键回主菜单...\n");
getchar();
}
}

我的基本思路是用stufun.c文件包含stuheader.h文件,然后用stuims.c包含stufun.c文件,本觉得万无一失,boom~boom~boom,error LNK2005来的如此突然、如此猛烈、瞬间呆若木鸡。

二:原因分析

首先我们看向stufun.c文件中的函数头,没有加static、extern等关键字,所以所有的自定义函数都默认为外部函数(int menu_select、int enter等等);

接下来我们再来分析#include:文件包含预处理是指在文件编译之前将源文件的全部内容包含进来(简单的说就是将源文件的所有代码copy过来代替该#include语句);

然后我们分析代码:

  1. 在stuims.c 有语句:#include<stufun.c>。
  2. 被包含文件(stufun.c)中含有全局变量或外部函数(int menu_select、int enter等等)

这样的话就导致项目中stufun.c有自定义函数的定义,而stuims.c中也有着一模一样的自定义函数的定义,所以就出现了error LNK2005(重复定义错误)

所以我们该怎么改呢?

三:代码修改

知道问题所在就简单了,我存在的问题是项目中有多个外部函数定义导致重复定义错误,所以我可以有两种解决方法:

  1. 在stufun.c中的所有自定义函数头处加extern关键字明确为外部函数,然后将#include "stufun.c"语句替换成#include "stuheader.h",No Error;
  2. 将stufun.c中的所有自定义函数头部加static关键字明确其为内部函数,问题解决!

四:问题总结

出现这样的问题在于做项目经验太少,定义函数时没有想到去添加其作用范围,以后再定义全局变量和外部函数时一定谨慎谨慎再谨慎,一定要明确自己所定义的变量及函数的作用范围,不然在软件扩展时会出现意料之外的Bug。话已至此,还是非常感谢Bug2005,所以我决定:我——AboutSange和error2005在2016.04.09结为异性兄弟,一起去找寻成神路上尚未碰面的error!

Error LNK2005 从敌人到朋友的更多相关文章

  1. VC&plus;&plus; &colon; error LNK2005&colon; &period;&period;&period; already defined in &ast;&period;obj

    今天写代码遇到了这么一个链接错误:"已经在*.obj中定义". error LNK2005: "void __cdecl ReplaceWstringVar(class ...

  2. win32 Dll 中添加afx&period;h 出现如下错误 error LNK2005&colon; &lowbar;DllMain&commat;12 already defined

    win32 Dll 中添加afx.h 出现如下错误 nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in ...

  3. error LNK2005&colon; &lowbar;DllMain&commat;12 已经在 dllmain&period;obj 中定义

    error LNK2005: _DllMain@ 已经在 dllmain.obj 中定义 今天遇到了同样的问题,搜索搜到了这里,后来解决了........ 创建解决方案时,用的是WIN32 DLL,添 ...

  4. ZZmsvcprt&period;lib&lpar;MSVCP90&period;dll&rpar; &colon; error LNK2005&colon;已经在libcpmtd&period;lib&lpar;xmutex&period;obj&rpar; 中定义 &period;的分析解决办法 &lpar;转&rpar;

    很久没有写程式设计入门知识的相关文章了,这篇文章要来谈谈程式库 (Library) 连结,以及关于 MSVC 与 CRT 之间的种种恩怨情仇. 如果你使用的作业系统是 Linux.Mac 或其他非 W ...

  5. error LNK2005 int &lowbar;&lowbar;cdecl 解决方案【转】

    error LNK2005: "int __cdecl isPtInPolygon(class std::vector<struct double2,class std::alloca ...

  6. uafxcwd&period;lib&lpar;afxmem&period;obj&rpar; &colon; error LNK2005 解决方法

    项目为非MFC,但要用到MFC的库,使用过程中遇到的问题总结一下 uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl opera ...

  7. 封装dll遇到的奇葩错误:error LNK2005&colon; &lowbar;DllMain&commat;12 已经在 DLLMain&period;obj 中定义

    在定义一个dll工程的时候,一添加MFC的头文件就会报出这个 错误:error LNK2005: _DllMain@12 已经在 DLLMain.obj 中定义  既蛋疼又蛋疼!! 然后逛论坛,查资料 ...

  8. error&colon;LNK2005 已经在&ast;&period;obj中定义

    为什么会出现这个错误??“error LNK2005: 已经在*.obj中定义”  编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难解决的错误,弄清楚它形成的原 ...

  9. VC error LNK2005 解决办法

    error LNK2005: "int __cdecl VerifyVMR9(void)" (?VerifyVMR9@@YAHXZ) 解决办法 在 属性->配置属性-> ...

随机推荐

  1. 64位进程池HashCode兼容处理

    背景 net旧项目使用32位生成的HashCode,存储到数据库中.迁移到64位上,就需要对HashCode做兼容处理. 解决方案 1:进程池配置支持32位程序. 2:对Hashcode做兼容处理,[ ...

  2. 使用SDWebImage下载图片&comma;sharedDownloader方法下载成功&comma;new 方法下载失败

    一,经历 1.使用 new 方法创建下载对象时,下载图片总是失败,而且不会执行成功或失败后的回调. 2.参考别人的代码,用的是sharedDownloader来创建下载对象,可以顺利下载图片. 3.看 ...

  3. python requests 配置超时及重试次数

    import requests from requests.adapters import HTTPAdapter s = requests.Session() s.mount('http://', ...

  4. Oracle的trunc和dbms&lowbar;random&period;value随机取n条数据

    今天在review项目代码的时候看到这样一个问题,有一张号码表,每次需要从这样表中随机取6个空闲的号码,也就是每次取出来的6个号码应该都会有所不同.然后我就看到了这样的SQL select   t.* ...

  5. 3月题外:关于GeoServer和OpenLayers3实用开源插件或组件的总结

    Geoserver篇 注意: 1)用法 GeoServer-Extension的使用方法:将jar包直接放入部署在tomcat上的geoserver/WEB-INF/lib文件夹中 2)在安装插件时, ...

  6. eclipse maven项目中使用tomcat插件部署项目

    maven的tomcat插件部署web项目,我简单认为分两种,一种是部署到内置tomcat,另一种是部署到安装的tomcat. 第一种部署,默认是部署在内置tomcat的8080端口,如果不需要改端口 ...

  7. Oracle启动操作

    转自:https://www.cnblogs.com/mellowsmile/p/4610942.html 1.启动oracle数据库: 从root切换到oracle用户进入:su - oracle ...

  8. Navicat Mysql快捷键

    .ctrl+q 打开查询窗口 .ctrl+/ 注释sql语句 .ctrl+shift +/ 解除注释 .ctrl+r 运行查询窗口的sql语句 .ctrl+shift+r 只运行选中的sql语句 .F ...

  9. Spring cloud系列之win10 下安装 ZooKeeper 的方法

    ZooKeeper 下载地址: https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/ 1.将下载的文件解压到指定的目录中 2.进入conf文件夹 ...

  10. 在VMware中安装Mac OS

    macOS与Darwin http://blog.csdn.net/hintcnuie/article/details/38468093 OS X 是整个操作系统的一个集体名称.而Darwin 就是其 ...