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 filemodule.c
. The module contains a global variable calledglobal_variable
.global_variable
will be updated by other functions in the implementation but we do not want users ofmodule
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 not 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 #undef
ing the macro.
#include "module.h"
int f(void)
{
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 for the implementation. */
#else
extern const int global_variable; /* `readonly` for 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. :)
static
) and providing a function to read its value. Or better yet, don't use a global variable if you can.