views:

3021

answers:

8

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!

+6  A: 

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 funtion (one in test.c and other in main.c)

Kasprzol
+3  A: 

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
+2  A: 

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
anon
+2  A: 

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
Up-vote for the nice diagram.
Ollie Saunders
+11  A: 

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
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.
anon
You should provide information about the parameters to test() in the header file, i.e. void test(); -> void test(void);
aib
I just took the interface suggested in the question, but you are right: I update my answer.
mouviciel
`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
LeonixSolutions
@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
+1 for a good answer.Thanks
LeonixSolutions
+1  A: 

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
A: 

Thanks for the help. I had the same problem too.

A: 

Thanks, that answer was helpful. Quick question though: what if we have a struct defined in one C file, and want to use it in another? Is there a quick way of writing it in the header file, or must I redefine it everywhere? Thanks

Kabir