mardi 6 janvier 2015

C: Using macros to protect assignment to global variables


Because there is no language feature in C to protect assignment to global variables would you recommend doing something like this?


Take this example:



We have a module with the header file called module.h and implementation file module.c. The module contains a global variable called global_variable. global_variable will be updated by other functions in the implementation but we do not want users of module to be able to assign to it.



module.h:



#ifndef MODULE_H_
#define MODULE_H_

extern int global_variable;
#define global_variable (int)global_variable
/* Because the macro expansion is an "lvalue" it cannot be assigned to. */

/* ... */

#endif


In the implementation you just #undef the macro to get full read/write access to it.


module.c:



#include "module.h"
#undef global_variable /* Make `global_variable` mutable again. */

int global_variable = 17;

/* ... */


This method obviously has the disadvantage that you cannot create a local variable with the identifier global_variable without #undefing the macro.



#include "module.h"

int f()
{
int global_variable; /* This doesn't work. */
/* ... */
}


But if you manage to come up with a naming convention that separates the identifiers this will not be a problem. Something like prefixing global variables with glbl_ or GLBL_. GLBL_ seems like a good choice since that also gives you a hint that it can be defined as a macro.


Another technique I have figured out is this:


module.h:



#ifndef MODULE_H_
#define MODULE_H_

#ifdef MODULE_IMPL_
extern int global_variable; /* Writable to the implementation. */
#else
extern const int global_variable; /* `readonly` to everyone else. */
#endif

#endif


module.c:



#define MODULE_IMPL_ /* I am the implementation. I want global_variable to be mutable. */
#include "module.h"

int global_variable = 17;
/* ... */


I know that the simplest and most flexible approach is to create get functions to retrieve the value of the variable at the cost of a function call. But that does not stop me from finding other hacks to solve the problem.


Are these evil things to do? I am not going to lie, I like to play with macros. But I want to know if this is something that can be applied to a serious project. :)





Aucun commentaire:

Enregistrer un commentaire