提问人:ErrorEliminator 提问时间:6/24/2023 最后编辑:Vlad from MoscowErrorEliminator 更新时间:6/24/2023 访问量:137
链接文件时无法解决多个定义错误 [重复]
Unable to resolve multiple definition error while linking files [duplicate]
问:
我正在研究本学期计算机编程课程中的一个问题,但无法解决我面临的链接器错误。有人可以看看以下文件并让我知道出了什么问题。按照指示,我放置了守卫以确保不会发生多个定义,但守卫似乎没有像我预期的那样运行,因为 gcc 给了我错误,说 count 和 booksCatalog 被多次定义。
以下是用于该问题的 C 文件和头文件。
book.h的
#ifndef BOOK_H
#define BOOK_H
#include <stdio.h>
typedef enum shelf{Shelf1=1,Shelf2=2,Shelf3=3,Shelf4=4} SHELF;
typedef struct book{
int ID;
SHELF shelfNum;
float price;
} BOOK;
// the function should create a new variable of the type struct book (typdefed as BOOK)
// using the parameters passed to it and return it.
BOOK newBook(int ID, SHELF shelfNum, float price);
// this function should print the values of the members of book1 (passed as parameter)
void printBook(BOOK book1);
#endif
book.c(图书.c)
#include "book.h"
BOOK newBook(int ID, SHELF shelfNum, float price)
{
// implement this function as per specification in books_def.h
BOOK newbook = {ID, shelfNum, price};
return newbook;
}
void printBook(BOOK book1)
{
// implement this function as per specification in books_def.h
printf("Book ID : %d\n", book1.ID);
printf("Book shelf number : %d\n", book1.shelfNum);
printf("Price of Book: %f\n\n",book1.price);
return;
}
目录.h
#ifndef CATALOG_H
#define CATALOG_H
#include "book.h"
#define MAX_SIZE 100
BOOK booksCatalog[MAX_SIZE];
int count;
// This function should take an input parameter of the type struct book (typdefed as BOOK)
// and it to the booksCatalog array at position count. Then, count should be incremented.
void addBookToCatalog(BOOK book1);
// This function should print all the books that are added to booksCatalog array.
// It should use the printBook() function defined in "book_def.h" to print the details of each book.
void printBookCatalog();
// This function should sort the booksCatalog array based on the ID of the book.
void sortBookCatalogOnID();
#endif
catalog.c网站
#include "catalog.h"
void addBookToCatalog(BOOK book1)
{
// implement this function as per specification in books_catalog.h
if (count<MAX_SIZE)
{
booksCatalog[count]=book1;
count++;
}
else
printf("Catalog is full!");
return;
}
void printBookCatalog()
{
// implement this function as per specification in books_catalog.h
for (int i=0; i<count; i++)
{
printBook(booksCatalog[i]);
}
return;
}
void sortBookCatalogOnID()
{
// implement this function as per specification in books_catalog.h
int min;
for (int i=0; i<count-1; i++)
{
min=i;
for (int j=i+1; j<count; j++)
{
if ((booksCatalog[j].ID)<(booksCatalog[min].ID))
min=j;
}
BOOK temp = booksCatalog[i];
booksCatalog[i]=booksCatalog[min];
booksCatalog[min]=temp;
}
return;
}
main.c
#include "catalog.h"
#include "book.h"
int main()
{
count = 0;
BOOK book1 = newBook(1847, Shelf3, 8768.95);
BOOK book2 = newBook(5984, Shelf1, 7845.25);
BOOK book3 = newBook(6325, Shelf2, 3154.47);
BOOK book4 = newBook(5843, Shelf2, 1487.51);
BOOK book5 = newBook(7894, Shelf2, 541.29);
// printBook(book1);
// adding book1 to catalog of books
addBookToCatalog(book1);
addBookToCatalog(book2);
addBookToCatalog(book3);
addBookToCatalog(book4);
addBookToCatalog(book5);
printBookCatalog();
sortBookCatalogOnID();
printBookCatalog();
return 0;
}
答:
标头有两个变量的暂定定义catalog.h
BOOK booksCatalog[MAX_SIZE];
int count;
由于标头包含在模块中,因此实际上这两个变量在每个翻译单元中定义两次,例如catalog.c
main.c
BOOK booksCatalog[MAX_SIZE] = { 0 };
int count = { 0 };
来自 C23 标准(6.9.2 外部对象定义)
2 具有文件范围的对象的标识符声明 没有初始值设定项,也没有存储类说明符,或者 使用存储类说明符 static,构成暂定 定义。如果翻译单元包含一个或多个暂定 标识符的定义,并且翻译单元不包含 该标识符的外部定义,则行为为 就像翻译单元包含文件范围声明一样 的标识符,其复合类型截至 转换单元,初始值设定项等于 {0}。
您应该在标头中声明不带定义定义的变量catalog.h
extern BOOK booksCatalog[MAX_SIZE];
extern int count;
(注意:这些声明中的变量不应初始化。否则,它们在标头中外部定义,链接器将再次发出错误,因为标头包含在两个转换单元中。
并在模块中定义它们,例如catalog.c
BOOK booksCatalog[MAX_SIZE] = { 0 };
int count = 0;
注意的是,在 C 中,与 C++ 相反,要使文件(C++ 中的命名空间)作用域变量的外部定义,您需要初始化它。在 C++ 中,没有“暂定定义”这样的概念。
在你的头文件中,你有一行catalog.h
int count;
这是一个暂定的定义。在这种情况下,这个暂定定义将始终成为实际定义。
这意味着两个源文件,每个文件都提供了变量的定义。这违反了单一定义规则,即使两个定义相同。main.c
catalog.c
count
为了遵守单一定义规则,只有一个源文件应提供定义。因此,我建议在头文件中更改行catalog.h
int count;
自:
extern int count;
这样一来,这一行将是一个声明,而不是一个暂定的定义。
但是,现在变量在 和 中声明,但未在任何地方定义。因此,为了遵守单一定义规则,还必须在其中一个源文件中定义变量。此定义可以是(暂定)定义count
main.c
catalog.c
int count;
或明确的定义:
int count = 0;
变量也有同样的问题。booksCatalog
评论
.c
#define
#define BOOK_H
评论