Search code examples
ccoding-styleglobal-variables

What is the most elegant way to work with global variables?


A couple years ago I learned that global variables are bad and should be avoided. But I know they are sometimes unavoidable, at least in an embedded system. What do you think is the most elegant way to work with them?

In my projects I have a file called globals.h where I define all my global variables:

#ifndef GLOBALS_H
#define GLOBALS_H
extern int16_t    gVariable1;
extern int16_t    gVariable2;
….
#endif

In my main project file I declare all global variables:

/*
***********************************************************************
*                            global variables                         *
***********************************************************************
*/
    int16_t     gVariable1 = 0;
    int16_t     gVariable2 = 0;


int16_t main (void)
{
    gVariable1 = 6;

    //  do other stuff
}

And know I include globals.h in every other file of the project which needs access to a global variable.

That works fine, but is there a more elegant way to handle that?


Solution

  • I am not sure that global variables are bad in all cases, but you really need to work hard to have very few of them (otherwise, your code in unreadable). For example <stdio.h> has stdout, and it won't be better if it was replaced by some FILE*get_standard_output(void); getter function.

    As a rule of thumb, avoid having more than 4 or 5 global variables in your entire program (recall the magical number seven as a hint on our cognitive limitations).

    However, you could pack (cleverly and with good taste, to keep your code readable) several related global variables into a single one of struct type. With your example, that could mean in your globals.h:

    struct globalstate_st { int16_t v1, v2; };
    

    then

    extern struct globalstate_st gs;
    

    and you would use gs.v1 instead of gVariable1; if you compile with optimizations, the performance of using gs.v1 is equivalent to using gVariable1.

    BTW, if you have a multi-threaded program, you generally should protect global data with some mutex (or some other kind of synchronization or atomicity). Consider reading this pthread tutorial.