How to define constants in headers to use in multiple C files - c

When writing C code, I might want to define a constant array in a header file so that it may be used in multiple .c files.
Take the following example:
main.c
#include <stdio.h>
#include "main.h"
int main() {
int localmat[9];
for (int i = 0; i < 9; i++) {
localmat[i] = HEADERMAT[i];
}
matadd(localmat, HEADERMAT);
return 0;
}
main.h
#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8};
// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif
functions.c
#include "main.h"
void matadd(int matA[9], const int matB[9]){
for (int i = 0; i < 9; i++) {
matA[i] += matB[i];
}
}
The constant array HEADERMAT declared in main.h is used in both
main.c and functions.h. The header does use ifndef to prevent redefinitions and yet, the compiler will still complain about it being defined multiple times:
/usr/bin/ld: /tmp/ccVWhI0u.o:(.rodata+0x0): multiple definition of `HEADERMAT'; /tmp/ccRAIQ5u.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
What would be the better way of making this array accessible to both C files?

Header files are for declarations. So, this is one way:
// main.h
#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
const int HEADERMAT[9]; // <---- declaration only
// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif
Then, in some source file (preferably main.c, since we declared in main.h)
// main.c
#include <stdio.h>
#include "main.h"
const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8}; // <---- definition here
int main() {
int localmat[9];
for (int i = 0; i < 9; i++) {
localmat[i] = HEADERMAT[i];
}
matadd(localmat, HEADERMAT);
return 0;
}
If you did it this way in the header file instead:
// main.h
// main.h
#ifndef _MAIN_H_
#define _MAIN_H_
// Constant array
static const int HEADERMAT[9] = {0,1,2,3,4,5,6,7,8}; // <-- static definition
// prototype function:
void matadd(int matA[9], const int matB[9]);
#endif
Then the array would be duplicated in every source file that included main.h, which, as the Jonathan Leffler's comments point out, is not that big of a deal (36 bytes). But for an array of appreciable size, the waste would be a concern.

If I understand you simply want to make the HEADERMAT[] array available in multiple source files, you can simply declare it as usual in any of the source files and then declare it as extern in any other source file that needs it.
To do so, you need to
define a macro for the array size in a common header so all sources will know the size of the array, e.g. #define HEADERMATSZ 9,
declare the array as usual in one of the C source files, e.g. const int HEADERMAT[HEADERMATSZ] = {0,1,2,3,4,5,6,7,8};,
in any other C source files that need access, declare extern const int HEADERMAT[HEADERMATSZ];.
Now you can simply use HEADERMAT[] as needed in any file where it is either declared originally, or as extern.
A short example, first the common header to be included by main.c and source1.c that holds a function that will use the array declared as extern, e.g.
#ifndef COMMONHDR
#define COMMONHDR 1
#define HEADERMATSZ 9 /* defined size of extern array */
void showoutput (void); /* declaration of function using extern array*/
#endif
For your main.c we will declare the array there, including the common header to provide the declaration for the function we will call from source1.c that uses the array declared extern, e.g.
#include <stdio.h>
#include "commonhdr.h"
const int HEADERMAT[HEADERMATSZ] = {0,1,2,3,4,5,6,7,8};
int main (void) {
puts ("output from other file");
showoutput();
}
(the showoutput() function being the function called from source1.c, also note HEADERMATSZ can be omitted if your initializer has the correct number of values -- including it ensures the array is sized correctly)
Finally the source1.c file we provide the function definition that uses the array extern,
#include <stdio.h>
#include "commonhdr.h"
extern const int HEADERMAT[HEADERMATSZ];
/* definition of function using extern array */
void showoutput (void)
{
for (int i = 0; i < HEADERMATSZ; i++) {
printf (" %d %d\n", i, HEADERMAT[i]);
}
}
Compile both sources into the final executable, e.g. with gcc,
gcc -Wall -Wextra -pedantic -Wshadow -std=c11 -Ofast source1.c -o main main.c
Example Use/Output
$ ./main
output from other file
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
This method works well regardless whether it is on your PC or programming a micro-controller. By using extern, the array need not be const and can be modified in either source if it is mutable.

Related

How to define variables in a header file, C

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;
}

Splitting up processes in different files

So I made a program that uses four differrent processes to do some stuff. I works perfectly, but now I want to split it up so each of the processes has its own .c file. I tried to do this using a header file "processes.h" that has the function prototypes for all the processes. It looks like this:
#ifndef PROCESSES_H_
#define PROCESSES_H_
/*------------------------------------------------------------------------------
definitions (defines, typedefs, ...)
------------------------------------------------------------------------------*/
#define NR_OF_PROCESSES 4
enum errCode {
ERR_NONE = 0, ERR_SYNTAX, ERR_OPEN, ERR_TOKEN, ERR_ARG, ERR_END
};
typedef enum errCode ErrCode;
enum toktype {
NUMBER = 0, OPERATOR, ENDOFLINE, ENDOFFILE
};
typedef enum toktype Token;
/*------------------------------------------------------------------------------
function prototypes
------------------------------------------------------------------------------*/
void readProcess(int pfds[5][2]);
void tokenProcess(int pfds[5][2]);
void calculatorProcess(int pfds[5][2]);
void errorProcess(int pfds[5][2]);
/*------------------------------------------------------------------------------
global variable declarations
------------------------------------------------------------------------------*/
void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2]) = {
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
};
#endif /*PROCESSES_H_*/
All the .c files which contain the implementation of the function #include "processes.h", and the main function (which uses the functionTable to set up the processes) also includes processes.h.
When I try to compile I get the error:
ld: duplicate symbol _functionTable in /var/folders/eH/eHF8LmdvHzSsNgT01V3jyk+++TI/-Tmp-//ccDgTW2X.o and /var/folders/eH/eHF8LmdvHzSsNgT01V3jyk+++TI/-Tmp-//ccp7zO9L.o
collect2: ld returned 1 exit status
Is this the right way of doing the splitting up into different files? Or do I need a separate .h file for each .c file?
Put this in your .h:
extern void *functionTable;
Then put this in exactly one file, e.g. the source file with "main()":
#include "processes.h"
...
void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2]) = {
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
};
One way to do this is to put
#ifdef GENERATE_DEFINITIONS
#define EXTERN
#define INITIALIZE(x) = x
#else
#define EXTERN extern
#define INITIALIZE(x)
#endif
EXTERN void (*functionTable[NR_OF_PROCESSES]) (int pfds[5][2])
INITIALIZE({
readProcess,
tokenProcess,
calculatorProcess,
errorProcess
});
in processes.h and then put
#define GENERATE_DEFINITIONS
before the
#include "processes.h"
in just one of the source files (e.g., the one containing main()).

Header/Include guards don't work?

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

Make a single definition from main.c to be available for a library at compile time

Lets say I have a main.c file
#include "library.h"
#define LIBRARY_VALUE 5
int main(void)
{
somefunction1();
return 0;
}
library.h
void somefunction1(void);
library.c
#include "library.h"
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
#endif
static unsigned char oneString[LIBRARY_VALUE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void)
{
printf("The Library Value is %d\n", LIBRARY_VALUE);
}
What I want to do here, is to be able to compile main.c and having LIBRARY_VALUE‘s value to be used as I defined right after the include in main.c.
How should I use GCC in order to achieve this?
I do need the value to be defined in main.c.
In case I have to change my code, I need a minimum working example code please. So I know clearly how to do this. Thanks.
In C there is no way for different .c files to share a common macro defined in one of the .c files. The tradition is to put it in a .h file, but you say this will not work for you.
You will need a type of "constructor" function that sets up your "static" information at run time. This constructor can be called directly by main.c, or indirectly by having main.c define an extern the library picks up.
I'll throw you some code, but I haven't tried to compile it... I'll leave that as an exercise for the student.
main.c
#include "library.h"
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
library.h
extern int const library_value;
void somefunction1(void);
library.c
#include <assert.h>
#include "library.h"
static unsigned char *oneString;
// destroy any memory from lib_init().
static void lib_clear(void)
{
if ( oneString )
{
free(oneString);
oneString = NULL;
}
}
// initialization - strop the static if the caller is to start it up.
static void lib_init( void )
{
if ( ! oneString ) // (defensive "if" to be sure)
{
assert( library_value > 0 );
oneString = (unsigned char*)malloc( library_value );
atexit( &lib_clear );
}
}
void somefunction1(void)
{
if ( ! oneString ) // if the main() is not calling an the constructor then
lib_init(); // // every method within the library must do so.
printf("The Library Value is %d\n", library_value);
}
The lib_init() and lib_clear() methods could be made externs with a lib_init( int size ) signature to take the size.
Your goal seems to have a single definition referenced multiple places.
There are a limited number of possibilities:
#define in .h
extern defined in main, or somewhere else outside of library.
extern defined in library.
Value passed by caller to library, perhaps an initialization call for the library.
Something defined before #include library.h that is picked up by library.h. I don't like this one.
As alfa says, make it a compile-time definition.
An example of a #define within library.h.
// library.h
#ifndef LIBRARY_VALUE
#define LIBRARY_VALUE 1
void somefunction1(void);
#endif
Or, have main define a value defined by the caller and referenced by the library:
// library.h
extern int const library_value; // caller to define in main
void somefunction1(void); // function for caller
// main.c
int const library_value = 5;
int main(void)
{
somefunction1();
return 0;
}
The one I don't like is:
//main.c
#define LIBRARY_VALUE 5
#include "library.h"
//library.h
#ifdef LIBRARY_VALUE
int const library_value = LIBRARY_VALUE; // executable code in .h files is evil
#endif
Some of the reasons I dont' like this is that it is obscure and unconventional, if two or more callers of library.h define LIBRARY_VALUE you will, or at least should, get obscure link time errors. The same applies if LIBRARY_VALUE is not defined by an #include... library.c itself can not define a default value. No, I'd much rather call an initialization function for the library that accepts the constant.
The problem with the way you seem to want this to work, is that the constant gets used when the library is compiled -- you can't use one value when compiling the library and then compile a program with a different value and expect the library's code to magically change to use the new constant. You have some options when it comes to alternatives, though.
You could move the array into the program rather than the library, and give the library a pointer to it, and its size.
Or you could use a dynamically allocated array in the library, and add an initialization function to do the allocation (using the size provided by the program).
Or, you could ditch the library and just compile its code as part of the program -- then you can use a constant defined for the program as long as its done where the (previously) library code will see it.
Recommendation (assuming you want "myarray" visible outside the library):
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
extern unsigned char myarray[ARRAY_SIZE]; // Also I need to be able
// to use the value to initialize
// static arrays that will be
// modified by somefunction1();
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
Otherwise, if you just want "somefunction1()" and the array size, then declare another function, "array_size ()":
// library.h
#ifndef LIBRARY_H
#define LIBRARY_Y
#define ARRAY_SIZE 5
int array_size (); // library.c will define "myarray" and it will
// define function array_size as "return ARRAY_SIZE;"
void somefunction1(void); // function for caller
#endif
/* LIBRARY_H */
ALSO:
Please remember that "static" has two meanings:
1) Hides visibility of a variable or function name to file scope (the name is "invisible" outside of the source file)
2) allocates space for the object from static storage (instead of the heap (malloc/new) or stack (local variables)).
If you only want the "static storage" part; then you don't need the keyword "static". Just define your variable outside of a function, and you're set :).
Yet another issue is whether you want to make "ARRAY_SIZE" a compile time variable. If so, you should make sure it gets defined EXACTLY ONCE (when library.c is compiled), and is used IN ONLY ONE PLACE (library.c and library.c only). For example:
// library.c
#include "library.h"
#ifndef ARRAY_SIZE
#error ARRAY_SIZE IS UNDEFINED!
#else
static unsigned char myarray[ARRAY_SIZE];
int array_size ()
{
return ARRAY_SIZE;
}
#endif
...
What you are trying to do is not possible because library.c and main.c are compiled separately. You should compile library.c with "gcc -DLIBRARY_VALUE=5 ..." instead.

how do i avoid this linking error?

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.

Resources