【问题标题】:Errors: multiple definition and first defined here错误:多重定义和第一次在这里定义
【发布时间】:2020-10-04 08:06:46
【问题描述】:

我尝试包含几乎所有标题组合。尝试使用以下方法编译目标文件:

gcc database.c -c
gcc database.o user_interface.c -o database

结果是:

/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

user_interface.c

#include "record.h"

int debugmode; 

int main(int argc, char *argv[])
{ 
    // my code here
}
    // other functions: AddRecord, printallRecords,...

数据库.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);

数据库.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...*/

记录.h

struct record
{
    int                accountno;
    char               name[25];
    char               address[80];
    struct record*     next;
};

【问题讨论】:

  • 根据 user_interface.c 中的注释,听起来您在两个文件中定义了相同的功能。这将有助于查看所有文件,而不仅仅是您认为相关的 sn-ps。
  • // other functions: AddRecord, printallRecords,... 问问自己为什么user_interface.cdatabase.c 都有这些。您确实在两个不同的源文件中提供了 same 函数的两个实现,并且链接器在尝试修复标识符时准确地告诉您。
  • @JoanaF。确切地。这完全是问题所在。从代码的外观来看,user_interface.c 应该包含用于类型声明的 record.h 和 database.h,并且这些 db 函数的实现应该在 database.c only 中。顺便说一句,您可能还需要在标题中包含保护围栏。
  • 你的构建命令也被打了。您应该使用 gcc -c -o database.o database.c 作为数据库对象代码,gcc-c -o user_inteface.o user_interface.c 作为 ui 对象代码,最后使用 gcc -o database user_interface.o database.o 作为最终链接。那,假设你做的一切都正确。
  • 如果user_interface.c正在调用database.h中声明的函数,那么它需要#include "database.h"

标签: c makefile


【解决方案1】:

你似乎遇到了很多麻烦,因为你在杂草丛中,往墙上扔东西。但如果你退后一步,从更高的层次上看,其实并没有那么难。

这里感兴趣的概念是声明定义。不幸的是,它们的名字如此相似:很容易混淆。

想一个定义比如你的房子,一个声明比如你房子的地址。您只有一所房子,但您可以将您的地址分发给许多不同的人。您的地址告诉人们如何去您家,但实际上并不是您家。

与C类似,函数的定义是函数的实际实现,函数的声明描述了如何调用函数。

声明如下所示:

void printAllRecords(struct record *);

(注意,没有函数体,只是它的调用方式),定义如下:

void printAllRecords(struct record *record)
{
    ...do some stuff...
}

(注意,现在你有了函数体)

您通常将 声明 放在头文件中。然后任何想调用你的函数的人都会#include那个头文件,这样他们就知道调用它的正确方法了。

但你不想#include函数的定义(例如,通过#include源文件),因为这意味着你有同一个函数的两个实现,这是不可能的,就像你的房子不能有两个一样。

所以,简而言之:

  • 将函数定义放入源文件中
  • 将函数声明放入头文件中
  • 你应该在包含定义的源文件中#include包含声明的头文件,这样如果它们不匹配,编译器就会报错
  • 最后,如果你想从其他源文件调用函数,#include 也包含该源文件中的声明的头文件

在您的情况下,database.c 中的所有定义函数都应该在database.h 中具有声明,然后任何其他源文件(如user_interface.c)应该@ 987654331@ 查看这些声明。

【讨论】:

  • 数据结构没有类似函数的“实现”,因此它们通常在头文件中同时声明和定义。那么任何需要该数据结构的源文件或头文件都应该包含该头文件。
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多