Mike
Mike

Reputation: 4288

What is the most elegant way to work with global variables in an embedded system?

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 with interrupts. 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:

global.h

#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:

main.c

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


int16_t main (void)
{
    gVariable1 = 6;

    //  do other stuff
}

And now 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?

Upvotes: 3

Views: 1818

Answers (3)

Moses
Moses

Reputation: 349

All of the answers to this question are so far good, but I would like to add something else here.

Take all of the recommendations to the code style with a grain of salt. Some of them came from the higher level languages and do not apply to C or assembly.

When I was just starting out with C, I tried to comply with all of the recommendations I took from OOP languages only to find out that they do not really work in C. If you take for example the Robert Martin book, he states there that a function should ideally contain 3-5 lines of code. Isn't this preposterous? Imagine writing a real world app that does something useful with this recommendations in mind. It's going to become a real mess really soon.

Upvotes: 0

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.

Upvotes: 3

Jossy Sebastian
Jossy Sebastian

Reputation: 155

Global variables are not dangerous. It help. But best practice, always keep the scope of the variable limited.

Set the global variable with static and expose function to get and set value.

Eg: in global.c

static int gMyGlobalVariable;

int getMyGlobalVariableValue()
{
   return gMyGlobalVariable;
}

void setMyGlobalVariableValue(int set)
{
   gMyGlobalVariable = set;
}

Eg: in global.h

void setMyGlobalVariableValue(int set);
int getMyGlobalVariableValue();

This will give better control on a multi threaded situation.

Upvotes: 3

Related Questions