57

I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code: main.c:

#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks

int main()
{
    //t = test(); // calling of method also not necessary
    return 0;
}

test.c:

void test() {}

When I try to build this program, it gives the following errors:

*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|

There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.

I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.

Does anyone know what is causing this and what I can do about it? Thanks!

Jordi
  • 5,846
  • 10
  • 40
  • 41

8 Answers8

114

You actually compile the source code of test.c twice:

  • The first time when compiling test.c itself,
  • The second time when compiling main.c which includes all the test.c source.

What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:

void test(void);

This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.

In main.c, replace #include "test.c" by #include "test.h".

A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:

#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED

void test(void);

#endif
mouviciel
  • 66,855
  • 13
  • 106
  • 140
  • Names such as _TEST.H_ that begin with an underscore and a capital letter are illegal in C user code - they are reserved for the compiler implementors. –  Mar 23 '09 at 10:13
  • You should provide information about the parameters to test() in the header file, i.e. void test(); -> void test(void); – aib Mar 24 '09 at 19:27
  • I just took the interface suggested in the question, but you are right: I update my answer. – mouviciel Mar 24 '09 at 20:11
  • 1
    `You actually compile the source code of test.c twice: •The first time when compiling test.c itself, •The second time when compiling main.c which includes all the test.c source.` and this is accepted as an answer?? (technically true, but it hardly answers) You complie each unit once. The compiler resolves what it can within the current file and then leaves hooks for the linker. It is the linker which will resolve your call to `test(); ` - and will have a problem determining which `test()` you actually mean – Mawg says reinstate Monica Jun 23 '10 at 07:51
  • 3
    @LeonixSolutions: My answer is a little bit more elaborate than what you quote. And it looks like it solved the problem of the OP. – mouviciel Jun 23 '10 at 09:54
  • not related to the topic at hand, but what is the point of the `#ifndef` there? – Snusifer Jan 11 '22 at 07:01
  • 1
    @Snusifer The point is to check whether the header file has already been included, in which case it shall not be included again. – mouviciel Jan 13 '22 at 07:50
29

The underscore is put there by the compiler and used by the linker. The basic path is:

main.c
test.h ---> [compiler] ---> main.o --+
                                     |
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe

So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:

void test(void);

This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.

It's the linking phase that joins together the two modules.

By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
12

You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.

The error is caused by multiple definitions of the test function (one in test.c and other in main.c)

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Kasprzol
  • 4,087
  • 22
  • 20
6

I had similar problem and i solved it following way.

Solve as follows:

Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.

Function definition and use of global variable in test.c file

if you initialize global variables in header it will have following error

multiple definition of `_ test'| obj\Debug\main.o:path\test.c|1|first defined here|

Just declarations of global variables in Header file no initialization should work.

Hope it helps

Cheers

eboix
  • 5,113
  • 1
  • 27
  • 38
Murad
  • 61
  • 1
  • 1
  • Awesome! thanks! I was beating my head against the wall and your answer to not initialize global variables in a header file fixed my problem! Many Thanks! – Jman Feb 03 '19 at 21:10
5

If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:

  • remove the #include "test.c"
  • create a file test.h which contains the declaration: void test();
  • include the file test.h in main.c

Community
  • 1
  • 1
4

Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:

/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
dirkgently
  • 108,024
  • 16
  • 131
  • 187
4

If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well .. .. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.

Good luck with it

cwap
  • 11,087
  • 8
  • 47
  • 61
2

Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.

I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)

The solution was to ONLY put a declaration in the header file and the definition in the cpp file.

The reason is that header files are not compiled, they only provide definitions.

Louis
  • 185
  • 1
  • 10