Search code examples
cgcclinker-errorsdeclarationdefinition

Unable to resolve multiple definition error while linking files


I am working on a question from my computer programming course this semester and am unable to resolve a linker error that I am facing. Can someone take a look at the following files and let me know what's wrong. As instructed, I placed guards to ensure multiple definitions don't take place but the guards don't seem to be functioning as I expected because gcc is giving me and error saying that count and booksCatalog are defined multiple times.

Below are the C files and header files used for the question.

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

#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;
}

catalog.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;
}

Solution

  • In your header file catalog.h you have the line

    int count;
    

    which is a tentative definition. In this case, this tentative definition will always become an actual definition.

    This means the two source files main.c and catalog.c are each providing a definition of the variable count. This violates the one-definition rule, even if the two definitions are identical.

    In order to comply with the one-definition rule, only one of the source files should provide a definition. Therefore, I suggest that in the header file catalog.h, you change the line

    int count;
    

    to:

    extern int count;
    

    That way, this line will be a declaration instead of a tentative definition.

    However, now the variable count is declared in main.c and catalog.c, but not defined anywhere. Therefore, in order to comply with the one-definition rule, you must also define the variables in one of the source files. This definition can be a (tentative) definition

    int count;
    

    or an explicit definition:

    int count = 0;
    

    The variable booksCatalog has the same problem.