我尝试包含几乎所有标题组合。尝试使用以下方法编译目标文件:
gcc database.c -c
gcc database.o user_interface.c -o database
Run Code Online (Sandbox Code Playgroud)
结果是:
/tmp/ccWfp2tS.o: In function `addRecord':
user_interface.c:(.text+0x4b9): multiple definition of `addRecord'
database.o:database.c:(.text+0x0): first defined here
/tmp/ccWfp2tS.o: In function `printAllRecords':
user_interface.c:(.text+0x54a): multiple definition of `printAllRecords'
database.o:database.c:(.text+0x1a): first defined here
/tmp/ccWfp2tS.o: In function `findRecord':
user_interface.c:(.text+0x590): multiple definition of `findRecord'
database.o:database.c:(.text+0x24): first defined here
/tmp/ccWfp2tS.o: In function `deleteRecord':
user_interface.c:(.text+0x5ed): multiple definition of `deleteRecord'
database.o:database.c:(.text+0x36): first defined here
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
用户界面.c
#include "record.h"
int debugmode;
int main(int argc, char *argv[])
{
// my code here
}
// other functions: AddRecord, printallRecords,...
Run Code Online (Sandbox Code Playgroud)
数据库.h
#include "record.h"
int addRecord (struct record **, int, char [ ],char [ ]);
void printAllRecords(struct record *);
int findRecord (struct record *, int);
int deleteRecord(struct record **, int);
Run Code Online (Sandbox Code Playgroud)
数据库.c
#include "database.h"
extern int debugmode;
int addRecord(struct record ** start, int account, char name[], char address[])
{
/*my code here*/
return 0;
}
/*other functions...*/
Run Code Online (Sandbox Code Playgroud)
记录.h
struct record
{
int accountno;
char name[25];
char address[80];
struct record* next;
};
Run Code Online (Sandbox Code Playgroud)
你似乎遇到了很多麻烦,因为你在杂草丛中,向墙上扔东西。但如果退一步,从更高的层面来看,其实并没有那么难。
这里感兴趣的概念是声明与定义。不幸的是他们的名字如此相似:很容易让他们混淆。
可以将定义想象为您的房屋,将声明想象为您房屋的地址。你只有一间房子,但你可以将你的地址分发给很多不同的人。您的地址告诉人们如何到达您的家,但它实际上并不是您的家。
类似地,在C中,函数的定义是函数的实际实现,函数的声明描述了如何调用该函数。
声明如下所示:
void printAllRecords(struct record *);
Run Code Online (Sandbox Code Playgroud)
(注意,没有函数体,只是调用它的方式)并且定义如下:
void printAllRecords(struct record *record)
{
...do some stuff...
}
Run Code Online (Sandbox Code Playgroud)
(注意,现在你有了函数的主体)
通常将声明放在头文件中。然后任何想要调用您的函数的人都会使用#include
该头文件,以便他们知道调用它的正确方法。
但是您不想#include
定义函数(例如,通过ing 源文件),因为这意味着您有同一函数的两个实现,而这是不可能的,就像您的房子不能有两个一样#include
。
所以,简而言之:
#include
包含声明的头文件放在包含定义的源文件中,这样如果它们不匹配,编译器就会抱怨#include
头文件也包含该源文件中的声明在您的情况下,中定义的所有函数都database.c
应该在 中具有声明database.h
,然后任何其他源文件(例如user_interface.c
)应该#include "database.h"
看到这些声明。