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?
CodePudding user response:
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.
CodePudding user response:
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.