Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including C header file with lots of global variables

Tags:

c

gcc

I have an include file with 100+ global variables. It's being used in a library, but some programs that I'm linking the lib to also need to access the globals.

The way it was built:

// In one library .c file
#define Extern

// In the programs that use the globals
#define Extern extern

// In the .h file
Extern int a,b,c;

I had a hard time understanding why the original programmer did that so I removed that define Extern stuff. Now I think I understand the thing about TU with the help of stackoverflow: 1, 2, 3.

Now I understand that I should define the global variables in one .c file in the library and use extern in the .h file. The problem is that I don't want to duplicate code.

Should I go back to that #define Extern voodoo?

like image 442
Costi Avatar asked May 19 '10 19:05

Costi


3 Answers

The trick here is that the .h file is being used in two different ways - it's being used as a normal .h file where all the globals are declared extern and it's also being used to define the globals themselves (with no extern). This is an ugly hack but you can understand why someone felt it necessary if you have a large number of globals (a sure sign of very bad software design !).

Anyway, there is a somewhat more elegant solution - you can put all your globals in a single global struct, e.g.

//
// globals.h
//

typedef struct {
    int a;
    int b;
    // ...
    int z;
} Globals;

extern Globals globals; // declaration

-

//
// globals.c
//

#include "globals.h"

Globals globals; // definition

-

Then when you need to refer to a global it's e.g. globals.a instead of just a, which might seem like an inconvenience but this is arguably clearer and more manageable than just having naked globals scattered throughout the code.

like image 156
Paul R Avatar answered Sep 28 '22 00:09

Paul R


It is a bad pattern to have to define Extern in every .c file. Removing it is probably best, but you need to replace this functionality somehow. One approach is that you could use a #define in the .c file that needs to define these globals. This define will signal to the .h to not extern the global variables.

For example: The one library .c file:

#define FOO_LIBRARY_C
#include "foo_library.h"

The other .c files:

#include "foo_library.h"

foo_library.h:

#ifdef FOO_LIBRARY_C
int a,b,c
#else
extern int a,b,c
#endif

or

#ifdef FOO_LIBRARY_C
#define GLOBAL_PREFIX
#else 
#define GLOBAL_PREFIX extern
#endif

GLOBAL_PREFIX int a,b,c

This reduces the need to define the same thing in every single source file (except one) and would help to reduce errors. I also wouldn't call it Extern as that can just cause confusion, as it may or may not be "extern"

like image 38
Aaron Avatar answered Sep 28 '22 00:09

Aaron


Maybe I'm missing something too, but I ALWAYS use inclusion guards on all the header files I create:

foo.h:

#ifndef FOO_H
#define FOO_H

extern int foo;

#endif

foo.c:

#include "foo.h"

int foo = 0;

bar.c:

#include "foo.h"
#include <stdio.h>
int main(int argc, char** argv)
{
    printf("foo:%d\n",foo);
    return 0;
}
like image 24
James Morris Avatar answered Sep 28 '22 00:09

James Morris