C - wrapping globals in a struct?

It is well-known bad practice to have a "super header" file like "globals.h" or "includes.h" etc, because in addition to globals being bad in the first place, this also creates a tight coupling dependency between every single, unrelated file in your project.

Lets say you have a PWM driver and a RS-232 debug print module. You want to grab the RS-232 debug print module and re-use it in another project. Suddenly you find yourself needing some PWM.h which you haven't got a clue about what it is or where the need comes from. You'll find yourself asking why on earth you need a PWM driver to run RS-232.

And then we haven't even considered re-entrancy of this messy global struct. Lets not even do that.


The correct way to untangle global spaghetti would rather be something like this:

  • Is the variable used in the first place? If not, remove. (This is quite common)
  • Can the variable be moved to local scope inside a function?
  • Can the variable be moved to local .c file scope by making it static? Can you reduce access to it from outside the .c file by implementing setter/getter functions?

If all of the above failed, then the variable you find yourself looking at should either be a memory-mapped hardware register part of a register map, or it is some real-time critical dirty fix that was added during maintenance.


It would work to define a struct that you instantiate as the single global variable. Accesses on the form 'the_global.the_var' won't add run-time overhead and can clarify that it's indeed a global. As https://stackoverflow.com/questions/2868651/including-c-header-file-with-lots-of-global-variables mentions, it saves you from separate declarations and definitions.

Personally I wouldn't bother to make a struct, instead preferring to sort globals into the header files where I feel they logically belong and use a common prefix for each header file. Example: File calculate.h declaring "extern int calc_result;" and calculate.c defining "int calc_result;"

Other variables get away with being file local, i.e. "static int result;" in the .c file.

Since you have legacy code that I guess you won't work a lot with beyond tidying it up, I'd say that the quickest solution that makes for a clear structure is the best.


If you can't get rid of the globals, I'd say you should only pack them together in a struct if they are actually related. If not, then I'd keep them separate or in smaller structs.

Also, I wouldn't like a globals.h file either. Keep them at the top of the source file where they most belong. This way when navigating through the code, you likely stay in the place where you were or go to the place you likely wanted to go.

Tags:

C

Firmware