Error LNK2005 從敵人到朋友,errorlnk2005
本人在寫學生信息管理系統時遇到一個很頭疼的錯誤——error LNK2005重復定義錯誤,苦思冥想百度谷歌bing之後都沒能解決問題,於一清早剎那間覺得知道問題出在哪兒了,於是乎起床、開機、修改代碼一氣呵成,終於0 error(s)\0 warning(s)。
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[20]; //學號
char name[20]; //姓名
char sex[5]; //性別
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 0;
}
//插入記錄函數,參數為結構體數組和記錄數
int add(STUDENTS t[],int n)
{
return 0;
}
//保存函數,參數為結構體數組和記錄數
void save(STUDENTS t[],int n)
{
}
//讀入函數,參數為結構體數組
int load(STUDENTS t[])
{
return 0;
}
//按序號顯示記錄函數
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 0;
}
//按學號查找函數,參數為記錄數組和記錄條數以及學號no
int find_no(STUDENTS t[],int n,char *no)
{
return 0;
}
//修改函數,按照輸入學號修改
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 0:length=enter(stu);break; //輸入記錄
case 1:list(stu,length);break; //顯示全部記錄
case 2:search(stu,length);break; //按姓名查找記錄
case 3:length=del(stu,length);break;//按姓名刪除記錄
case 4:modify(stu,length);break; //按學號修改記錄
case 5:length=add(stu,length);break;//插入記錄
case 6:save(stu,length);break; //保存文件
case 7:length=load(stu);break; //加載文件到內存
case 8:display(stu,length);break; //按序號顯示記錄
case 9:sort(stu,length);break; //按姓名排序
case 10:copy();break; //復制文件到目標文件
case 11:exit(0); //程序結束
}
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語句);
然後我們分析代碼:
這樣的話就導致項目中stufun.c有自定義函數的定義,而stuims.c中也有著一模一樣的自定義函數的定義,所以就出現了error LNK2005(重復定義錯誤)
所以我們該怎麼改呢?
三:代碼修改
知道問題所在就簡單了,我存在的問題是項目中有多個外部函數定義導致重復定義錯誤,所以我可以有兩種解決方法:
四:問題總結
出現這樣的問題在於做項目經驗太少,定義函數時沒有想到去添加其作用范圍,以後再定義全局變量和外部函數時一定謹慎謹慎再謹慎,一定要明確自己所定義的變量及函數的作用范圍,不然在軟件擴展時會出現意料之外的Bug。話已至此,還是非常感謝Bug2005,所以我決定:我——AboutSange和error2005在2016.04.09結為異性兄弟,一起去找尋成神路上尚未碰面的error!