I have the problem, that in CCS I encounter unexpected redefenition errors if I include headers.
Minimal example:
// main.c
#include "test.h"
int main(void)
{
init();
return 0;
}
with
// test.h
#ifndef TEST_H_
#define TEST_H_
int var;
void init();
#endif /* TEST_H_ */
and
// test.c
#include "test.h"
void init()
{
var=0;
}
I get
error #10056: symbol "_var" redefined: first defined in "./main.obj";
redefined in "./test.obj"
on compilation. I'm pretty sure this should work in any C using IDE.
What do I miss?
" I'm pretty sure this should work in any C using IDE". No it doesn't.
Every time you include test.h in a C file, the variable var is not only declared but also defined, hence the compilation error.
Include guards are not designed to avoid multiple definitions across translation units, but more to adress multiple inclusions of the same header file in a single translation unit.
See for example https://fr.wikipedia.org/wiki/Include_guard
The proper way to adress this issue is to only declare your variable in the header file:
extern int var;
and then define the variable only once in a C file (without extern).
int var;
Related
below is the code:
//test.h
...
extern int globalVariable;
...
//test.c
#include "test.h"
...
int globalVariable = 2020;
...
//main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("Value is %d", globalVariable);
}
let's say in a scenario, there are hundreds of variables are declared in test.h and globalVariable is just one of them.
since there are two many variables, I easily makes a typo error in test.c as:
#include "test.h"
int globalVariables = 2020; //extra 's' in the name which contradicts the declaration of its counterpart in test.h
if I compile(only compile,not linking them) test.c, test.h and main.c, it compiles and shows no error. the unresolved error will only occur when linker involved in the linking stage.
But in a large application, I might just write some modules without the need of linking all existing to an executable file, so it would be better the compiler throw an error in the compile stage to indicate the error so I can correct them asap, so how can I let the compiler force the source file implement definition for a header file?
You could also use the preprocessor
test.h:
#ifndef TEST_C_IMPLEMENTATION
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
extern type name;
#else
#define DEFINE_AND_INIT_VARIABLE(type, name, value) \
type name = value;
#endif
DEFINE_AND_INIT_VARIABLE(int, globalVariable, 2020);
test.c:
#define TEST_C_IMPLEMENTATION
#include "test.h"
This technique can be taken even further - there are small utility libraries that are shipped as a single include file; you're just to set a macro in one of the translation units to force the implementation to be compiled in there.
The declaration extern int globalVariable; says that the variable exists somewhere, but not necessarily in the current translation unit. So any source file that includes the header containing this declaration will know that the variable exists without needing the full definition.
When you then get to the linking stage is when you'll get the error regarding glovalVariable being undefined. Since the variables is declared in test.h, convention would dictate that the definition would be in test.c. Upon inspecting that file, you would then find that no such variable exists and could then either add it or find the typo and fix it.
I'm a beginner learning c. I know that use of word "static" makes a c function and variable local to the source file it's declared in. But consider the following...
test.h
static int n = 2;
static void f(){
printf("%d", n);
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("%d", n);
f();
return 0;
}
My expected result was that an error message will throw up, since the function f and variable n is local to test.h only? Thanks.
But instead, the output was
2
2
EDIT:
If it only works for a compilation unit, what does that mean? And how do I use static the way I intended to?
static makes your function/variable local to the compilation unit, ie the whole set of source code that is read when you compile a single .c file.
#includeing a .h file is a bit like copy/paste-ing the content of this header file in your .c file. Thus, n and f in your example are considered local to your main.c compilation unit.
Example
module.h
#ifndef MODULE_H
#define MODULE_H
int fnct(void);
#endif /* MODULE_H */
module.c
#include "module.h"
static
int
detail(void)
{
return 2;
}
int
fnct(void)
{
return 3+detail();
}
main.c
#include <stdio.h>
#include "module.h"
int
main(void)
{
printf("fnct() gives %d\n", fnct());
/* printf("detail() gives %d\n", detail()); */
/* detail cannot be called because:
. it was not declared
(rejected at compilation, or at least a warning)
. even if it were, it is static to the module.c compilation unit
(rejected at link)
*/
return 0;
}
build (compile each .c then link)
gcc -c module.c
gcc -c main.c
gcc -o prog module.o main.o
You have included test.h in main.c.
Therefore static int n and static void f() will be visible inside main.c also.
When a variable or function is declared at file scope (not inside any other { } brace pair), and they are declared static, they are local to the translation unit they reside in.
Translation unit is a formal term in C and it's slightly different from a file. A translation unit is a single c file and all the h files it includes.
So in your case, the static variable is local to the translation unit consisting of test.h and main.c. You will be able to access it in main.c, but not in foo.c.
Meaning that if you have another .c file including test.h, you'll get two instances of the same variable, with the same name. That in turn can lead to all manner of crazy bugs.
This is one of many reasons why we never define variables inside header files.
(To avoid spaghetti program design, we should not declare variables in headers either, unless they are const qualified.)
What are advantages and disadvantages of both approaches?
Source vs. header implementation
Function definition inside source file
Header file sourcefunction.h contains declaration only.
#ifndef SOURCEFUNCTION_H
#define SOURCEFUNCTION_H
void sourcefunction(void);
#endif // SOURCEFUNCTION_H
Source file sourcefunction.c contains definition
#include "sourcefunction.h"
#include <stdio.h>
void sourcefunction(void) { printf(" My body is in a source file\n"); }
Function definition inside header file
Header file headerfunction.h contains definition which is the declaration at the same time.
#ifndef HEADERFUNCTION_H
#define HEADERFUNCTION_H
#include <stdio.h>
void headerfunction(void) { printf(" My body is in a header file\n"); }
#endif // HEADERFUNCTION_H
No source file is needed.
Consumer
File main.c
#include "sourcefunction.h"
#include "headerfunction.h"
int main(void) {
sourcefunction();
headerfunction();
return 0;
}
Why compile many source files?
We have to compile all source files and remember about them during linking.
gcc -c sourcefunction.c
gcc -c main.c
gcc main.o sourcefunction.o
Make can handle file managing but why even bother?
Is separation of interface and implementation always an issue?
It is obvious reason for big projects and teamwork. The designer specifies the interface. The programmers implement functionality.
What about smaller projects and non-formal approach?
Is removing definition from header files always preventing from linker errors?
Let's assume my program is using another module that defines the function with the same name sourcefunction().
#include "sourcefunction.h"
#include "sourcefunction1.h"
#include "headerfunction.h"
int main(void) {
headerfunction();
sourcefunction();
return 0;
}
Different function interface
File sourcefunction1.h
#ifndef SOURCEFUNCTION1_H
#define SOURCEFUNCTION1_H
int sourcefunction(void);
#endif // SOURCEFUNCTION1_H
File sourcefunction1.c
#include "sourcefunction1.h"
#include <stdio.h>
int sourcefunction(void) { int a = 5; return a; }
By compiling main.c, I get a nice compiler error
sourcefunction1.h:4:5: error: conflicting types for 'sourcefunction'
showing me the location of error.
Same function interface
File sourcefunction1.h
#ifndef SOURCEFUNCTION1_H
#define SOURCEFUNCTION1_H
void sourcefunction(void);
#endif // SOURCEFUNCTION1_H
File sourcefunction1.c
#include "sourcefunction1.h"
#include <stdio.h>
void sourcefunction(void) { int a = 5; printf("%d",a); }
Compiler does not mind multiple declarations. I get ugly linker error.
Can header implementation serve as library?
jschultz410 says
If you are writing a library and all your function definitions are in headers, then other people who do segment their development into multiple translation units will get multiple definitions of your functions if they are needed in multiple translation units
Lets' have
File consumer1.c
#include "headerfunction.h"
void consume1(void) { headerfunction(); }
File consumer2.c
#include "headerfunction.h"
void consume2(void) { headerfunction(); headerfunction();}
File twoConsumers.c
extern void consume1(void);
extern void consume2(void);
int main(void) {
consume1();
consume2();
return 0;
}
Let's compile sources.
gcc -c consumer1.c
gcc -c consumer2.c
gcc -c twoConsumers.c
So far, so good. Now, linking.
gcc consumer1.o consumer2.o twoConsumers.o
Linker error: multiple definition of 'headerfunction', of course.
But I can make my library function static.
File headerfunction.h, afterwards.
#ifndef HEADERFUNCTION_H
#define HEADERFUNCTION_H
#include <stdio.h>
static void headerfunction(void) { printf(" My body is in a header file\n"); }
#endif // HEADERFUNCTION_H
It hides the definition from other translation units.
I shouldn't answer this, but I will.
This can create duplicate definitions unless you really only have a single .c file in your project (unwise). Even the header guards won't prevent files the headers from being included multiple times if those multiple times are with different .c files. When the .obj files are linked together, there will be conflicts.
If only the function declaration and not definition is in the header, then only changes to the interface (the function name, parameters or return type) require recompiling dependencies. However, if the entire definition is in the header, then any change to the function requires recompiling all .c and .h files that depend on it, which, in a larger project, can create a lot of unnecessary recompiling.
It's not the convention. Libraries will not use this convention, so you'll be stuck dealing with their header file structure. Other developers will not use this convention, so you can create confusion or annoyance there.
For some reason, I'm getting multiple declarations of content within my header file even though I'm using header guards. My example code is below:
main.c:
#include "thing.h"
int main(){
printf("%d", increment());
return 0;
}
thing.c:
#include "thing.h"
int increment(){
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
int something = 0;
int increment();
#endif
When I attempt to compile this, GCC says that I have multiple definitions of the something variable. ifndef should make sure that this doesn't happen, so I'm confused why it is.
The include guards are functioning correctly and are not the source of the problem.
What happens is that every compilation unit that includes thing.h gets its own int something = 0, so the linker complains about multiple definitions.
Here is how you fix this:
thing.c:
#include "thing.h"
int something = 0;
int increment(){
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment();
#endif
This way, only thing.c will have an instance of something, and main.c will refer to it.
You have one definition in each translation unit (one in main.c, and one in thing.c). The header guards stop the header from being included more than once in a single translation unit.
You need to declare something in the header file, and only define it in thing.c, just like the function:
thing.c:
#include "thing.h"
int something = 0;
int increment(void)
{
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment(void);
#endif
The header guards will stop the file from being compiled more than once in the same compilation unit (file). You are including it in main.c and thing.c, so it will be compiled once in each, leading to the variable something being declared once in each unit, or twice in total.
try to avoid defining variables globally.
use functions like increment() to modify and read its value instead.
that way you can keep the variable static in the thing.c file, and you know for sure that only functions from that file will modify the value.
The variable something should be defined in a .c file, not
in a header file.
Only structures, macros and type declarations for variables and function prototypes
should be in header files. In your example, you can declare the type of something as extern int something in the header file. But the definition of the variable itself should be in a .c file.
With what you have done, the variable something will be defined
in each .c file that includes thing.h and you get a
"something defined multiple times" error message when GCC tries to link
everything together.
what ifndef is guarding is one .h included in a .c more than once. For instance
thing. h
#ifndef
#define
int something = 0;
#endif
thing2.h
#include "thing.h"
main.c
#include "thing.h"
#include "thing2.h"
int main()
{
printf("%d", something);
return 0;
}
if I leave ifndef out then GCC will complain
In file included from thing2.h:1:0,
from main.c:2:
thing.h:3:5: error: redefinition of ‘something’
thing.h:3:5: note: previous definition of ‘something’ was here
I'm trying to understand how global variables and functions work in C. My program compiles and works fine with gcc, but does not compile with g++. I have the following files:
globals.h:
int i;
void fun();
globals.c:
#include "stdlib.h"
#include "stdio.h"
void fun()
{
printf("global function\n");
}
main.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun();
int main()
{
i=1;
myfun();
return 0;
}
And finally, myfun.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun()
{
fun();
}
I get the following error when compiling with g++:
/tmp/ccoZxBg9.o:(.bss+0x0): multiple definition of `i'
/tmp/ccz8cPTA.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Any ideas why? I would prefer to compile with g++.
Every file you include globals.h from will define "int i".
Instead, put "extern int i;" into the header file and then put the actual definition of "int i = 1;" in globals.c.
Putting header guards around globals.h would be sensible too.
Edit: In answer to your question its because a #include works kind of like a cut and paste. It pastes the contents of the included file into the c file that you are calling include from. As you include "globals.h" from main.c and myfun.c you define int i = 1 in both files. This value, being global, gets put into the table of linkable values. If you have the same variable name twice then the linker won't be able to tell which one it needs and you get the error you are seeing. Instead by adding extern on the front in the header file you are telling each file that "int i" is defined somewhere else. Obviously, you need to define it somewhere else (and ONLY in one place) so defining it in globals.c makes perfect sense.
Hope that helps :)
I would add an include guard in your globals file
#ifndef GLOBALS_H
#define GLOBALS_H
int i;
void fun();
#endif
Edit: Change your globals to be like this (using extern as the other answer describes)
globals.h
extern int i;
extern void fun();
globals.c
#include "stdlib.h"
#include "stdio.h"
int i;
void fun()
{
printf("global function\n");
}
I compiled it with
g++ globals.c main.c myfun.c
and it ran ok
Several things wrong here; several other things highly recommended:
globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H
extern int my_global;
#ifdef __cplusplus
extern "C" {
#endif
void fun();
#ifdef __cplusplus
}
#endif
#endif
/* GLOBALS_H */
globals.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
int my_global;
void fun()
{
printf("global function: %d\n", my_global);
}
main.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
void myfun();
int main()
{
my_global=1;
myfun();
return 0;
}
void myfun()
{
fun();
}
You should declare "extern int myvar" in your header, and actually allocate "int myvar" in one and only one .c file.
You should include "globals.h" in every file that uses "myvar" - including the file where it's allocated.
Especially if you're planning on mixing C and C++ modules, you should use 'extern "C"' to distinguish non-C++ functions.
System headers should be "#include <some_header.h>"; your own headers should use quotes (#include "myheader.h") instead.
Short variable names like "i" might be OK for a strictly local variable (like a loop index), but you should always use longer, descriptive names whenever you can't avoid using a global variable.
I added a "printf" for my_global.
'Hope that helps!
I had this problem when porting some old C code to C++. The problem was it was a project that was connected to a database, and i wanted to port the database to c++ but not the rest. The database pulled in some C dependencies that couldn't be ported, so i needed the C code that overlapped both the database and the other project to compile in g++ as well as gcc...
The solution to this problem is to define all variables as extern in the .h file. then when you compile in either gcc or g++ it will report symbols missing in the .c files. So edit the .c files in the error messages and insert the declaration into all the .c files that need the variables. Note: you may have to declare it in multiple .c files, which is what threw me and why I was stuck on this problem for ages.
Anyway this solved my problem and the code compiles cleanly under both gcc and g++ now.