Global variables

From vegard.wiki
Revision as of 09:52, 10 February 2020 by Vegard (talk | contribs) (new page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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.