I want to declare and define (with a default value) a variable in a .h file.
When I do that I get
/tmp/cc19EVVe.o:(.data+0x0): multiple definition of `car_name'
/tmp/cc3twlar.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
How do I achieve my goal? Namely, to declare and define with default values a variable in a .h file and use that variable in multiple .c files?
Here is the A.h file
char * car_name = "Volkswagen";
void execute();
Here are the first file that uses the variable car_name defined in A.h: (The file is called execute.c)
#include "A.h"
#include <stdio.h>
#include <string.h>
void execute(){
int len = sizeof(car_name) + 2;
char car_name_with_new_line[len];
strncat(car_name_with_new_line, car_name, sizeof(car_name));
strncat(car_name_with_new_line, "\n", 1);
printf(car_name_with_new_line);
}
That's the other .c file: (It's called main.c)
#include "A.h"
int main(int argc, char ** argv){
execute();
return 0;
}
The answer is simple: Define your variables in exactly one compilation unit (.c file). Declare them in the header file associated with that .c file.
foo.h
extern char *g_name; // Declare that g_name exists
foo.c
#include "foo.h"
char *g_name; // Define g_name in one place
static char *m_private; // Private to foo.c, not "exported" via foo.h
main.c
#include "foo.h"
void somefunc(void)
{
// use g_name
}
1) define the variable in a single file, do not add a static modifier
2) place an extern statement for that variable in the header file.
then only one instance of the variable exists anyone that includes the header file can access the variable.
Note: it is poor programming practice to have global variables.
Good programming practice is to write accessor functions and hide the variable within a file. similar to the following:
static int myVariable = 0;
void setMyVariable( int myVariableParm )
{
myVariable = myVariableParm;
}
int getMyVariable( void )
{
return myVariable;
}
Related
For example:
In main.c
static glob_var;
I want to modify the value of glob_var in another file say file1.c
Making an variable static makes its identifier inaccessible from other translation unit (what usually means other C-file). You can either
Make the variable non-static.
//main.c
int glob_var;
//file1.c
extern int glob_var;
Note that the declaration should be put to a header file.
Keep it static and add a helper function for access.
//main.c
static int glob_var;
void SetGlobVar(int val) {
glob_var = val;
}
//file1.c
void SetGlobVar(int);
void foo(void) {
SetGlobVar(42);
}
Note that the declaration of SetGlobVar() should be put to a header file.
The comments and other answer address the question of how to access and modify a static global". The following is offed as an alternative to using static for this purpose...
When needing to create a variable that is global and can be changed among several translation units I believe it is more idiomatic to use the externstorage class. This is typically done by:
Declaring the extern variable in a header file
Defining the extern variable one-time-only in a .c file that #includess the header file.
Access and modify the extern class variable from any translation unit that #includes the header file in which the extern is declared.
Example:
in some.h:
void modify_glob_var(int val);
...
extern int glob_var;//declare extern variable
in main.c
#include "some.h"
...
int glob_var = 0;// define extern variable
...
modify_glob_var(10);//access and modify extern variable
in some_other.c
include "some.h"
...
void modify_glob_var(int val)
{
glob_var = val;//value of extern glob_var is changed here
}
A toy code illustrating my problem is as follows:
stuff.h:
#ifndef STUFF
#define STUFF
int a;
int testarr[]={1,2,3};
#endif
fcn.h:
#include "stuff.h"
int b[]={5,6,7};
void fcn();
main.h:
#include "stuff.h"
#include <stdio.h>
fcn.c:
#include "main.h"
void fcn() {
printf("Hello\n");
}
main.c:
#include "main.h"
#include "fcn.h"
int main() {
fcn();
printf("HI\n");
}
An attempt to compile fails with:
/g/pe_19976/fcn_2.o:(.data+0x40): multiple definition of `testarr'
/g/pe_19976/main_1.o:(.data+0x40): first defined here
After doing some reading, I realize that defining the array testarr in the header file is a problem. But the thing is, in my real code, several files need access to testarr and it needs to have the same assigned values everywhere. I guess I could put it in main.h (?) but even if that would work, in my real code it logically belongs in stuff.h. How do I solve this conundrum?
BTW, based on something else I found, I tried defining testarr as extern but got the same problem.
When you put a variable definition into a header file, any .c file that includes it will have a copy of that variable. When you then attempt to link them, you get a multiple definition error.
Your header files should contain only a declaration of the variable. This is done using the extern keyword, and with no initializer.
Then in exactly one .c file, you put the definition along with an optional initializer.
For example:
main.c:
#include "main.h"
#include "fcn.h"
int a;
int testarr[]={1,2,3};
int main() {
fcn();
printf("HI\n");
}
stuff.h:
#ifndef STUFF
#define STUFF
extern int a;
extern int testarr[];
#endif
fcn.h:
#include "stuff.h"
extern int b[];
void fcn();
fcn.c:
#include "main.h"
int b[]={5,6,7};
void fcn() {
printf("Hello\n");
}
It is not clear why you are using so many global variables. The array
int testarr[]={1,2,3};
is defined as many times as there are compilation units (in your example there are at least two compilation units) that include the corresponding header.
Declare the array in a header like
extern int testarr[3];
and define it in a cpp module.
int testarr[]={1,2,3};
The same is valid for other global variables that have external linkage.
As for this remark
BTW, based on something else I found, I tried defining testarr as
extern but got the same problem.
Then the array with the specifier extern shall not be initialized in a header. Otherwise it is a definition of the array.
Why we don't use extern when using function from one .c file in another .c file , but we must do extern for variables case? Is it related to linker?
Functions are extern qualified by default (unless you change it to internal with static). For example,
int func(void) {
}
extern int func2(void) {
}
Both func and func2 are external. The extern keyword is optional for external functions.
Actually, function names act just like variable names, but function prototypes are extern by default.
From cpprerefence:
If a function declaration appears outside of any function, the identifier it introduces has file scope and external linkage, unless static is used or an earlier static declaration is visible.
you can create a .hfile,declare functions you want to use in the other .c files and #include the .hfile in the other .c files.
Demo program,
one.c
#include "one.h"
void func1() //defination
{
//code
}
one.h
void func1(); //declaration
main.c
#include <stdio.h>
#include "one.h"
int main()
{
func1();
}
Then compile program in Gcc Linux : gcc main.c one.c
Yes, Let consider you have one .c file as process.c and you declared it in process.h . Now if you want to use the function from process.c to suppose tools.c then simply #include "process.h" in tools.c and use ther function. The process.h and process.c file should be in your project.
process.c file
#include<stdio.h>
#include<conio.h>
#include "process.h"
unsigned int function_addition(unsigned int a, unsigned int b)
{
unsigned int c = 0;
c = a + b;
return c;
}
process.h:
<bla bla bla >
unsigned int function_addition(unsigned int a, unsigned int b);
<bla bla bla >
tools.c file:
#include<stdio.h>
#include<conio.h>
#include "process.h"
my_tools()
{
unsigned int X = 1, Y = 9, C = 0;
C = function_addition(X,Y);
}
All these files are in one project.
I have a bunch of parameters (integers and floats); I want to write a C code where both the main program and the functions refer to the same parameters so that if I change one of them the whole code knows the new value I set. My code is formed by a main.c file which calls a function.c file; right now I declared the parameters both in the main and in the function but I think that is not robust (if I change one parameters in the main and I forget to change it also in the function I get wrong results). So here is the question: How can declare the parameters in order to change it just once and not to change it everywhere I have defined?
PS: i don't want to use #define because it doesn't allow me to specify whether it's an integer or not.
You can use a global variable, define it at the top of the main.c file and refer it at the top of the other .c file using the declaration "extern".
main.c
#include
...
int a;//global variable
function.c
include ...
extern int a;//global variable
You can use global variables.
Create a .h files -- let's call it globals.h. Put declarations of the global variables in the file.
extern int var1;
extern float var2;
extern double var3;
Create a .c file -- let's call it globals.c. Define the variables in the file.
#include "globals.h"
int var1 = 0;
float var2 = 10.0f;
double var3 = 200.0;
Use #include "globals.h" in any .c file in which you want to access the global variable.
#include "globals.h"
int main()
{
printf("var1 : %d\n", var1);
printf("var2 : %f\n", var2);
printf("var3 : %lf\n", var3);
}
If you change the values of var1, var2, or var3 anywhere in the program, the change will take effect for all the functions that access them.
You could use static consts, to all intents and purposes your effect will be achieved.
myext.h:
#ifndef _MYEXT_H
#define _MYEXT_H
static const int myx = 245;
static const unsigned long int myy = 45678;
static const double myz = 3.14;
#endif
myfunc.h:
#ifndef MYFUNC_H
#define MYFUNC_H
void myfunc(void);
#endif
myfunc.c:
#include "myext.h"
#include "myfunc.h"
#include <stdio.h>
void myfunc(void)
{
printf("%d\t%lu\t%f\n", myx, myy, myz);
}
myext.c:
#include "myext.h"
#include "myfunc.h"
#include <stdio.h>
int main()
{
printf("%d\t%lu\t%f\n", myx, myy, myz);
myfunc();
return 0;
}
if i have defined a global variable(with initialization) in header file, and included this file in two file and try to compile and link, compiler gives linking error
headers.h:
#ifndef __HEADERS
#define __HEADERS
int x = 10;
#endif
1.c:
#include "headers.h"
main ()
{
}
2.c:
#include "headers.h"
fun () {}
The linker complains because there will be multiple definitions of x once it puts all the object files together to create the executable. You have two different source files including the same header file, and that header file defines a variable x having a value of 10, so you end up with two definitions of x (one in 1.c and another in 2.c).
To avoid multiple definition linker errors, put this in a header file (for example globals.h):
#ifndef GLOBALS_H
#define GLOBALS_H
/*
* The "extern" keyword means that this variable is accessible everywhere
* as long as this declaration is present before it is used. It also means
* that the variable x may be defined in another translation unit.
*/
extern int x;
#endif
Then put this in one source file:
#include "globals.h"
int x = 10;
This is a classic case where you want either the variable declared or declared-and-defined.
If you define it in both source files, you will get a double-definition linker error. One way to handle this is to only set __HEADERS for one of the source files so that it is the one where the variable is defined.
All other source files get the declaration only.
>>headers.h
#ifndef __HEADERS
int x = 10;
#else
extern int x;
#endif
>>1.c
#define __HEADERS
#include "headers.h"
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
Of course, it's best to leave definitions out of header files altogether in case you accidentally define __HEADERS in two source files. Try:
>>headers.h
extern int x;
>>1.c
#include "headers.h"
int x = 10;
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
#include works exactly the same as if you copied and pasted the text from the header file.
Consider it in that way and you will see that you have therefore put the line int x=10 into both your source files.
A fixed version is below:
>>headers.h
#ifndef __HEADERS
#define__HEADERS
extern int x; // extern tells the compiler it will be linked from another file
#endif
-----------------
>>1.c
#include "headers.h"
int x = 10; // must have it in ONE file for linking purposes
main ()
{
}
---------------------
>>2.c
#include "headers"
fun () {}
Define __HEADERS in the ifndef.
Put declarations, not definitions, in your headers:
// header
extern int x;
// implementation
int x = 10;
3. 2.c has the include wrong.
So:
// headers.h
#ifndef __HEADERS
#define __HEADERS
extern int x;
#endif
// 1.c
#include "headers.h"
int x = 10;
main ()
{
}
// 2.c
#include "headers.h"
fun () {}
You can define x anywhere. Just make it one place.