Question

I am dealing with the following issue in C. I use global variables for defining some global parameters in my code. I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file. In a nutshell, I am looking for a good way to "cast away" constness during variable initialization in C (I guess in C++ this would not be an issue thanks to const_cast)

I came up with a pattern based on macros to do so, as illustrated below. It seems to work fine, but I have the following questions. Does anyone see any hidden flaw or potential danger in the procedure below? Would anyone discourage the following approach in favor of a simpler one?

My approach:

I have a main header file containing the definition of my global variable (int N) like so

/* main_header.h */

#ifdef global_params_reader
#define __TYPE__QUAL__
#else
#define __TYPE__QUAL__ const
#endif

__TYPE__QUAL__ int          N;

I have a file "get_global_params.c" implementing the initialization of N, which sees N as "int N" (as it includes "main_header.h" after defining global_params_reader)

/* get_global_params.c */

#define global_params_reader
#include get_global_params.h

void get_global_params(char* filename){

    N = ... ; // calling some function that reads the value of N from 
              // the datafile "filename" and returns it

}

and the corresponding header file "get_global_params.h"

/* get_global_params.h */

#include "main_header.h"

void get_global_params(char* filename);

Finally, I have a main.c, which sees N as "const int N" (as it includes "main_header.h" without defining global_params_reader):

/* main.c */

#include "main_header.h"
#include "get_global_params.h"

int main(int argc, char **argv){

    // setting up input data file //
    ...

   // initialize N //
   get_global_params(datafile);

   // do things with N //
   ...
}

I hope my explanation was clear enough. Thanks for any feedback.

Was it helpful?

Solution

Just contain the globals in a separate file.

globl.h:

struct Globals{
  int N;
  //...
};

extern const struct Globals *const globals;

init_globl.h:

init_globals(/*Init Params*/);

globl.c

#include globl.h
#include init_globl.h

static struct Globals _globals;
const struct Globals *const globals = &_globals;

init_globals(/*Init Params*/){
  // Initialize _globals;
  //...
}

Now you can initialize the globals at startup by including init_globl.h in whatever file needs access to that functionality, everyone else can directly access the globals just by including globl.h, and using the notation globals->N.

OTHER TIPS

If I were you, I would simply avoid this kind of global variables. Instead, I would define a struct with all those program parameters, and define one function that returns a const pointer to the one and only instance of this struct (singleton pattern). That way, the function that returns the pointer has non-const access to the singleton, while the entire rest of the program does not. This is precisely what you need, it's clean and object oriented, so there is no reason to mess around with macros and casts.

The instance can be declared as a static variable within the function or it can be malloc'ed to a static pointer. It does not really matter, because that is an implementation detail of that function which is never leaked to the outside. Nor does the rest of the code need to be aware of when the parameters are actually read, it just calls the function and it gets the one and only object with all valid parameters.

"I would like such global variables to be constant, even though they have to be initialized inside a routine that reads their values from an input data file."

It is not possible to initialize a const in c during run-time. In c value either has or has not a const qualifier, and it is defined upon declaration. c does not support changing it. The semantics are fixed. But some expert with quoting the standard would be nicer and more ensuring.

I don't think this is possible in c++ either, but I won't bet on it, since c++ can do some magic here and there.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top