function definition in header file(c using gcc) - c

I am writing a simple c test framework. For simplicity, I only provide a single header file (containing all the function definitions), but I meet some problems. If I only include the header once, everything works fine. If I include the header twice, the gcc linker report duplicate symbol error (that is normal), so I add static prefix in every function in the header. This time it works, but the function is duplicate in the final binary. See bellow:
[heidong#HEIDONGVM ztest]$ nm m | grep __ct_hex_dump
0000000000400904 t __ct_hex_dump
0000000000401efc t __ct_hex_dump
Is there some way the made the function define only once?
Thanks a lot!!
Maybe someone needs the code, I just started a project in github: https://github.com/buf1024/test
Thanks again!!

What you have is in ct.h
static functions
static function definitions
In atest.c
// This is the first lot of definitions
#include "ct.h"
In main.c
// This is the second lot of definitions
#include "ct.h"
To fix
move the static function definitions to ct.c, remove the word static
Change all the prototypes in ct.h from static to extern
add ct.c to your link.
Edit: just delivering just ct.h
Change all the prototypes in ct.h from static to extern
Before the first function body add #ifdef __CT_C__
After the last function, add #endif
Tell the user that in the code that contains main, they need to #define __CT_C__ before they #include "ct.h"
Anything else that #include "ct.h" must not define __CT_C__.

Use compiler directives.
#IFNDEF MYFUNC
#DEFINE MYFUNC
myfunc();
#ENDIF
Everytime the compiler hits this directive, it will only go in once when MYFUNC is not defined and after defining it, it won't go in the statement again. No matter how many times you include the header file, it will always check if it's been defined before.
Coppiler directives is not part of the compiled code. It's just a directive.

If you absolutely need only one file, you can do it with preprocessor:
header.h
#ifndef HEADER_H
#define HEADER_H
#ifdef IMPLEMENT
#undef IMPLEMENT
void func(void) {
...
}
#else
void func(void);
#endif
#endif
In one file:
// Define
#define IMPLEMENT
#include "header.h"
In other files:
// Only declarations
#include "header.h"
Though I would choose a proper .c file instead.

Related

using user defined header file C

I'm confused about how to create a user defined header files and how to use it, so I'd like to ask if I get it correct.
If I have two C programs, one is demo.c and one is called tree.c, and I can create a header file tree.h:
#ifndef TREE_H
#define TREE_H
//some prototypes here
int size();
int isFull();
#endif
and in the actual tree.c program I put all the actual functions,
#include "tree.h"
int size()
{
//some implementation
}
int isFull()
{
//some implementation
}
I'm wondering if I have another program called demo.c, can I just include the tree.h header and use the function in the tree.c? just like what we do in Java using another class?
Do I need to put them in the same directory?
In short, yes, you can just do #include "tree.h" in demo.c.
If tree.h isn't in the same directory as demo.c, you can either include its path via #include "some/other/dir/tree.h" or you could pass an include flag in your compiler invocation. For example, if you're using gcc, you could do -Isome/other/dir.
demo.c only needs to see the function prototypes which tree.h contains so that it knows what kind of functions it's calling. tree.c isn't needed until you want to compile this into an executable.

Macro used in a .c file getting compiled without adding the header file in which it is defined

I have a large project where some macro is defined as:
#define RECORD_COUNT 141 // in one file file1.h
Another file say file2.c is using this macro. But the file2.c is not including file1.h.
So is there a possibility that in on compiling the first file get pre-compiled is file1.h and the macro is added to the global scope. And this makes it possible to pre-compile the file2.c?
Very likely your macro definition are compiling before you are using it somewhere.
Just to check you can use pragma message to check if compiler touches that code.
http://msdn.microsoft.com/en-us/library/x7dkzch2.aspx
You do not need to include the header file directly to use it. There can be indirect includes as well.
For example,
Say file1.h has
#define RECORD_COUNT 141
file2.h has,
#include "file1.h"
...
...
If file2.c has #include "file2.h" then, you can use any macros or definition that are in 'file1.h' inside file2.c after that include statement.

Trouble with #ifdef across multiple files

util.h contains the following code:
#ifdef DEBUG
#define LOGGER() MACRO_WRAP(printf("Entering %s\n", __func__))
#else
#define LOGGER() MACRO_WRAP()
#endif
foo.c contains this code:
void foo_start(foo *m)
{
LOGGER();
do_action(m, START);
}
and then foo_unit_tests.c contains calls to foo_start(). I'd like to be able to #define DEBUG at the top of the relevant files -- i.e. I want it to be turned on for unit tests, but not for the main code.
I can't get it to work. Putting #define DEBUG at the top of foo_unit_tests.c doesn't produce the desired behavior. The only way I can get it to work is by putting #define DEBUG either at the top of util.h or foo.c, both of which are much messier than I would like.
What am I missing here? I thought that the macro defined in the .c file would be visible inside of all of the .h files that it included.
You have to have the #define at the beginning of all your files that need that macro defined, or through including a .h file that has it in it.
If you want a cleaner way of doing that, then it is probably better to use the compiler flags to set environmental variables.
For example
icpc -DDEBUG=whatever source.c ...
Or even better, you can enable this compiler flag though an environmental variable in your makefile.
foo_unit_tests.c most likely does not include foo.c, so the #define there is never seen when compiling foo_unit_tests.c
define your normal logger somewhere.. the in the unit test..
#undef LOGGER()
#define LOGGER(x) fprintf(stdout, x)
or alternately you could do something like:
#ifdef UNITTEST
#define LOGGER ...
#else
#define LOGGER ...
#endif
and you pass in the UNITTEST macro from the build env when you build test

Multiple definition of in C

I have a project written in C consisting of FIFO.h, FIFO.c, task.h, task.c and main.c (it's a basic queue).
When I compile my main.c using gcc under Windows it compiles and works just fine. However when I try to compile the exact same code in Eclipse, I get the following error for every function:
One example is:
In function `queue_new':
FIFO\Debug/../src/QueueFIFO.c:20: multiple definition of `queue_new'
src\main.o:FIFO\Debug/../src/QueueFIFO.c:20: first defined here
src\FIFO.o:
I honestly have no idea what additional information you guys could use so just tell me what to do.
main.c includes:
#include "FIFO.h"
#include "FIFO.c"
#include "task.h"
QueueFIFO.c:
#include "task.h"
FIFO.c:
#include "task.h"
#include "QueueFIFO.c"
task.c:
#include "task.h"
You are getting multiple definition errors because you are including your .c files in your .c files. It's the linker's job to make sure they come together. Good practice is to only include .h files in your .c files, and make sure the .h files don't include function definitions (only function prototypes).
By #includeing your .c files, you are defining the functions at least twice: once when FIFO.c is compiled, and again when main.c (which #includes FIFO.c, copying it verbatim into the text before compilation) is compiled. When it comes to link time, the linker sees e.g. queue_new() defined in both FIFO.o and main.o and barfs on the multiple definition of all the functions in FIFO.c.
In addition, as others mentioned, make sure you "guard" your header files to make sure they don't create circular #include dependencies. You can do that with #ifndef and #define as follows:
/* foo.h */
#ifndef FOO_H
#define FOO_H
#include "bar.h"
#include "baz.h"
/* header file contents go here */
#endif /* FOO_H */
This has the effect of only executing the contents of the file once, since FOO_H will be defined if it is included a second time, and the entirety of the file will be skipped over.

How to prevent multiple definitions in C?

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!
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
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().
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)
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
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 */
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
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
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.

Resources