james harris james harris - 21 days ago 7
C Question

Multiple definitions of ... (linker error?)

I'm getting some kind of compiler/linker error in my code, most probably preprocessor related. the error message reads "multiple definitions of x", where x is any of the 4 functions in my lib.c file. the compiler/linker I am using is the GNU GCC compiler packaged with code:blocks

I have tried changing the order of the #includes to no success, and what leads me to believe that this is a linker error as opposed to a compiler error is the fact that if I make a deliberate syntax error, the compiler will spot that and abort without giving the error message.

all help/advice/criticism appreciated, thanks in advance!

here is the main.c file:

#include <stdlib.h>
#include "lib.c"

int main()
{
getGradeAverage();
return EXIT_SUCCESS;
}


and the lib.c:

#include "defs.h"

void getUserName ()
{
printf ("please enter the your name:");
studentRecord sr;
scanf("%40[^\n]%*c",&sr.studentName);
}

void getCourse (index)
{
printf("please enter the name of course 1:");
courseRecord cr1;
scanf("%40[^\n]%*c",&cr1.courseName);
do{
printf("please enter a grade for course 1:");
if ((scanf("%i",&cr1.grade))>-2)
{
printf("the grade you entered is not on the scale. please try again:");
fflush(stdin);
continue;
}
} while(true);
printf("please enter the name of course 2:");
courseRecord cr2;
scanf("%40[^\n]%*c",&cr2.courseName);
do{
printf("please enter a grade for course 1:");
if ((scanf("%i",&cr2.grade))>-2)
{
printf("the grade you entered is not on the scale. please try again:");
fflush(stdin);
continue;
}
} while(true);

}

void GPAPrint ()
{
int GPA;
studentRecord sr;
courseRecord cr1;
courseRecord cr2;
printf("Student name: %s\n",&sr.studentName);

}

void getGradeAverage ()
{
int index=1;
getUserName();
getCourse(index);
GPAPrint();
return (0);

}


the defs.h file is also relevant here, as this contains most of the #includes and structs.

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#define MAX_LENGTH 40

typedef struct courseRecord
{
char courseName [MAX_LENGTH+1];
int grade;
}courseRecord;

typedef struct studentRecord
{
char studentName [MAX_LENGTH+1];
char courseName[2];
}studentRecord;

Answer

Presumably, you have included lib.c in your build, as well as #includeing it in main.c. This causes the compiled objects (say, lib.o and main.o) to each have definitions of the functions. The linker picks this up (since it examines all the object files, whereas the compiler produces one at a time, so cannot detect instances where two or more objects files define something more than once) and complains about multiple definitions.

As a guideline, never #include a .c file.

Instead, place declarations (aka prototypes) of your functions in a header file (say lib.h)

 #ifndef LIB_H_INCLUDED
 #define LIB_H_INCLUDED

 #include "defs.h"

 void getUserName();
 void getCourse (index);

  // etc

 #endif

and #include that in every .c file that needs to use the functions. This provides enough information so the compiler can check if you are calling the functions correctly. Then place the function definitions (aka their implementations) in lib.c. lib.c will also need to #include "lib.h", so (among other things) the compiler can check if the declarations of the functions from the header match the definitions.

I've also placed include guards in the header. I'll leave it as an exercise for you to google to work out why.

Comments