Search code examples
cglobal-variablesprogram-structure

C - program structure (avoiding global variables, includes, etc.)


I'm using C (not C++) and I'm unsure how to avoid using global variables.

I have a pretty decent grasp on C, its syntax, and how to write a basic application, but I'm not sure of the proper way to structure the program.

How do really big applications avoid the use of global variables? I'm pretty sure there will always need to be at least some, but for big games and other applications written in C, what is the best way to do it?

Is there any good, open-source software written strictly in C that I could look at? I can't think of any off the top of my head, most of them seem to be in C++.

Thanks.

Edit

Here's an example of where I would use a global variable in a simple API hooking application, which is just a DLL inside another process.

This application, specifically, hooks API functions used in another application. It does this by using WriteProcessMemory to overwrite the call to the original, and make it a call to my DLL instead.

However, when unhooking the API function, I have to write back the original memory/machine code.

So, I need to maintain a simple byte array for that machine code, one for each API function that is hooked, and there are a lot.

// Global variable to store original assembly code (6 bytes)
BYTE g_MessageBoxA[6];

// Hook the API function
HookAPIFunction ( "user32.dll", "MessageBoxA", MyNewFunction, g_MessageBoxA );

// Later on, unhook the function
UnHookAPIFunction ( "user32.dll", "MessageBoxA", g_MessageBoxA );

Sorry if that's confusing.


Solution

  • "How do really big applications avoid the use of global variables?"

    1. Use static variables. If a function needs to remember something between calls, use this versus global variables. Example:

      int running_total (int num) {
          static int sum  = 0;
          sum             += num;
          return sum;
      }
      
    2. Pass data via parameters, so that the value is defined one place, maybe main() and passed to where it is needed.

    3. If all else fails, go ahead and use a global but try and mitigate potential problems.

      1. At a minimum, use naming conventions to minimize potential conflicts. EG: Gbl_MyApp_DeveloperName. So all global variables would start with the Gbl_MyApp_ part -- where "MyApp" was something descriptive of your app.
      2. Try to group functions by purpose, so that everything that needs a given global is in the same file (within reason). Then globals can be defined and restricted to that file (beware the extern keyword).