Global variables
Global variables are discouraged by a lot of people for various different reasons [1]. One objection is that it becomes harder to reason about (and test) functions because they have a "hidden" input (i.e. the global state).
I think global variables have their place, and are honestly not that different from, say, instance variables used by methods. One way to simply make it clear that global state is used in the code would be to provide a couple of wrappers for defining and declaring the use of global variables, respectively:
Definition:
#define DEFINE_GLOBAL(type, name) __thread typeof(type) global_##name
#define USE_GLOBAL(name) typeof(global_##name) &name = global_##name
Usage:
#include <cstdio>
DEFINE_GLOBAL(int, x);
void foo()
{
USE_GLOBAL(x);
printf("x = %d\n", x);
}
#if 0 // doesn't work, since x is undeclared
void bar()
{
printf("x = %d\n", x);
}
#endif
// complex type declarations also work:
DEFINE_GLOBAL(void (*)(int), fn);
If you want to be able to override the global for a function (e.g. for testing using mock data, without actually modifying the global), one could even put the declaration in the parameter list:
void baz(USE_GLOBAL(x))
{
printf("x = %d\n", x);
}
This function can be called either as
baz()
in which case it will use the actual global variable, or
int value = 12;
baz(value);
but here, the argument may not be a temporary expression.