Search code examples
cconstantsheader-files

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


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?


Solution

  • 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

    1. 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,
    2. 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};,
    3. 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.