Search code examples
cglobaltypedef

define array length struct with global constant from other file


In my model I have quite some parameters that are used by a lot of different functions. To make changing settings easy, I want to use one file for all my paramaters, keeping it sepperate from any of the "real programming".
That file is called parameters.c
In it, all parameters are defined like:

#define N 1000
#define T 1373

In a different c file (MyLib.c), I create a struct type:

typedef struct Model{
  struct Element el[N];
};

both files are included in my main script using:

#include "parameters.c"
#include "MyLib.c"

The project can not be build this way. However, if I move the line

#define N 1000

from parameters.c to MyLib.c, it works.
I could just create the struct to have an array that is larger than any N value I'd use, but that doesn't seem like the correct way to do it.

Is there a correct way to implement this, or would I indeed have to create the large array? (in the comments it was said the definition of correct is too broad. In this instance I mean memory efficient. I don't want to allocate a much larger chunck of memory than I need to.)

Thanks in advance.


Solution

  • Is there a correct way to implement this

    You library may look like this:

    // parameters.h
    #ifndef PARAMETERS_H_
    #define PARAMETERS_H_
    
    // documentation
    #define PARAMETERS_COUNT_OF_ELEMENTS    1000
    // this parameters does that and that
    #define PARAMETERS_DESCRIPTIVE_NAME     1373
    //      ^^^^^^^^^^^ - consistent namespace naming
    
    #endif
    

    // mylib.h - safe yourself trouble and DoN'T mIx UppErCaSe with lOwErcAsE
    // escapecially in header names
    // subjectively, I do not like pascal case - snake case rule them all!
    #ifndef MYLIB_H_
    #define MYLIB_H_
    #include "parameters.h"
    #include "element.h" // for struct element
    
    /// This structure represents a model in our library.
    struct mylib_model {
       //  ^^^^^^ - consistent namespace naming
    
       /// These are super important elements we deeply care about.
       struct element el[PARAMETERS_COUNT_OF_ELEMENTS];
    
    };
    
    /**
     * @brief this function does that and that
     * @return 0 on success, otherwise error
     *
     * Write documentation keeping consistent style, for example
     * use doxygen.
     */
    int mylib_do_something(struct mylib_model *the_model);
    
    #endif
    

    // mylib.c
    #include "mylib.h"
    
    int mylib_do_something(struct mylib_model *t) {
         // do something here
         // return 0 on success, otherwise document error codes, or use the ones from errno.h
         return 0;
    }
    

    // main.c
    #include "mylib.h"
    int main() {
        struct mylib_model model = {0};
        int err = mylib_do_something(&model);
        if (err != 0) { abort(); }
        return 0;
    }
    

    Your parmeters.h is very similar to the way autoconf projects generate config.h present in many GNU projects. Many projects use a configuration file, sometimes generate automatically by a build system. Nowadays if choosing build automation software I would recommend cmake. Other links: kernel coding style and google coding style.