0

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.

Kvaestr
  • 77
  • 6
  • 3
    Do *not* include a `.c` file in another, instead you should include `.h` files – Cory Kramer Oct 28 '20 at 11:40
  • I might have completely misunderstood the include mechanics, but I thought all definition type things had to be in .c files, whereas all functions had to be in header files. – Kvaestr Oct 28 '20 at 11:46
  • See [this question](https://stackoverflow.com/questions/1695224/what-do-c-and-h-file-extensions-mean-to-c#:~:text=c%20file%20is%20the%20C,it%20like%20a%20reference%2Fappendix.) and [this question](https://stackoverflow.com/questions/333889/why-have-header-files-and-cpp-files) – Cory Kramer Oct 28 '20 at 11:52
  • 1
    Typically all _definitions_ should be in .c, _including_ functions definitions, all _declarations_ go in .h, including function declarations. – KamilCuk Oct 28 '20 at 11:58
  • Okay, then I should make the parameters.c into parameters.h, but keep MyLib.c? At least that seems to work. Thank you – Kvaestr Oct 28 '20 at 12:03
  • I think this question is too broad, with no change of giving definitive exact short answer. For "correct way" research existing libraries and research how they do it. – KamilCuk Oct 28 '20 at 12:05
  • With correct, I mean efficient. The amount of memory it takes if I simply define a 1e6 size array would not be astronomical, but it isn't neat if I only use 1e5. either way with neither the .h or the .c file this is a way it works. – Kvaestr Oct 28 '20 at 12:11
  • "Correct" is subjective, and in my mind "correct" means bug free, maintainable, easy to introduce to new maintainers, with efficiency not being in any way cared about. (I do not understand how the amount of memory and what the numbers 1e6 1e5 do here) – KamilCuk Oct 28 '20 at 12:15

1 Answers1

2

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.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111