You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言链接文件时出现多重定义错误,头文件保护无效求排查

问题排查:全局变量多重定义的链接错误

问题背景

完成计算机编程课程作业时遭遇链接错误:gcc提示count和booksCatalog存在多重定义。已添加头文件保护,但问题仍未解决,相关代码如下:

原代码文件

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;

BOOK newBook(int ID, SHELF shelfNum, float price);
void printBook(BOOK book1);

#endif

book.c

#include "book.h"

BOOK newBook(int ID, SHELF shelfNum, float price)
{
    BOOK newbook = {ID, shelfNum, price};
    return newbook;
}

void printBook(BOOK book1)
{
   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;
}

catalog.h(错误根源文件)

#ifndef CATALOG_H
#define CATALOG_H

#include "book.h"

#define MAX_SIZE 100

// 错误:在头文件中直接定义全局变量
BOOK booksCatalog[MAX_SIZE];
int count;

void addBookToCatalog(BOOK book1);
void printBookCatalog();
void sortBookCatalogOnID();

#endif

catalog.c

#include "catalog.h"

void addBookToCatalog(BOOK book1)
{
    if (count<MAX_SIZE)
    {
        booksCatalog[count]=book1;
        count++;
    }
    else
        printf("Catalog is full!");
    return;
    
}

void printBookCatalog()
{
    for (int i=0; i<count; i++)
    {
        printBook(booksCatalog[i]);
    }
    return;
}

void sortBookCatalogOnID()
{
    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);

    addBookToCatalog(book1);
    addBookToCatalog(book2);
    addBookToCatalog(book3);
    addBookToCatalog(book4);
    addBookToCatalog(book5);

    printBookCatalog();

    sortBookCatalogOnID();

    printBookCatalog();

    return 0;
}

错误原因

头文件保护(#ifndef/#define/#endif)仅能防止单个源文件重复包含同一头文件,无法解决多个源文件包含同一头文件时的全局变量重复定义问题。

你在catalog.h中直接定义了全局变量booksCatalog和count,当main.c和catalog.c都包含该头文件时,两个源文件会各自生成一份变量定义。链接阶段编译器发现同一变量存在多份定义,因此抛出多重定义错误。

解决方法

遵循C语言编码规范:头文件中仅声明全局变量,在单个源文件中定义全局变量。

步骤1:修改catalog.h,将变量定义改为extern声明

#ifndef CATALOG_H
#define CATALOG_H

#include "book.h"

#define MAX_SIZE 100

// 用extern声明变量,告知编译器变量在其他文件中定义
extern BOOK booksCatalog[MAX_SIZE];
extern int count;

void addBookToCatalog(BOOK book1);
void printBookCatalog();
void sortBookCatalogOnID();

#endif

步骤2:在catalog.c中定义全局变量并初始化

在catalog.c开头添加变量定义,同时初始化count为0(避免未初始化全局变量的风险):

#include "catalog.h"

// 全局变量仅在此处定义,整个程序中仅一份实例
BOOK booksCatalog[MAX_SIZE];
int count = 0;

// 原函数实现保持不变
void addBookToCatalog(BOOK book1)
{
    if (count<MAX_SIZE)
    {
        booksCatalog[count]=book1;
        count++;
    }
    else
        printf("Catalog is full!");
    return;
    
}

void printBookCatalog()
{
    for (int i=0; i<count; i++)
    {
        printBook(booksCatalog[i]);
    }
    return;
}

void sortBookCatalogOnID()
{
    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;
}

步骤3:修改main.c,移除重复初始化

由于count已在catalog.c中初始化,删除main.c中的count = 0;语句:

#include "catalog.h"
#include "book.h"

int main()
{
    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);

    addBookToCatalog(book1);
    addBookToCatalog(book2);
    addBookToCatalog(book3);
    addBookToCatalog(book4);
    addBookToCatalog(book5);

    printBookCatalog();

    sortBookCatalogOnID();

    printBookCatalog();

    return 0;
}

验证修改

重新编译链接,多重定义错误将被修复。此时booksCatalog和count仅在catalog.c中有一份定义,其他文件通过extern声明引用该定义,符合C语言的链接规则。

内容的提问来源于stack exchange,提问作者ErrorEliminator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:50:00