0

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;
Thefoilist
  • 137
  • 1
  • 11
  • And what exactly is the "some kind of compiler/linker error in my code"? BTW You should have put function prototypes for the 4 functions, in the header file. – Weather Vane Nov 12 '16 at 20:06
  • I specified further down, the error message is "multiple definitions of ...", or do you mean something else? – Thefoilist Nov 12 '16 at 20:09
  • Of `x`. What is `x`. – Weather Vane Nov 12 '16 at 20:09
  • either the functions GPAPrint, getUserName, getCourse or getGradeAverage . the same error appears for all 4. – Thefoilist Nov 12 '16 at 20:11
  • 1
    How exactly are you compiling? – dbush Nov 12 '16 at 20:13
  • 1
    Why have you included `lib.c` in `main.c`? It should be the header file `lib.h`. And looking at some of the functions, they are doing nothing, with local variables. – Weather Vane Nov 12 '16 at 20:13
  • For example in `void GPAPrint ()`, the statement `printf("Student name: %s\n",&sr.studentName);` the variable `sr` is an uninitalised local variable, and the argument for `%s` should be `sr.studentName`, not `&sr.studentName`. You have a lot more problems than you say. – Weather Vane Nov 12 '16 at 20:16
  • if I move the include for lib.c into defs.h, and put an include for defs.h in main, it will not give any output unless i forcibly stop the compiler, at which point it gives the error "#include nested too deeply". yeah, thanks for spotting that, it apperas I didn't quite understand it in the lecture :) – Thefoilist Nov 12 '16 at 20:19

1 Answers1

1

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.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • thanks! could I also put the prototypes at the bottom of defs.h using the same format? I have no idea what guards are yet, but I'll do some research – Thefoilist Nov 12 '16 at 20:45
  • You could. All the preprocessor does is text substitution. Whether that's a good idea or not, depends on your project needs. – Peter Nov 12 '16 at 20:49
  • it works! (say in evil scientist accent for best effect). thanks for your time! – Thefoilist Nov 12 '16 at 20:52