Including C header file with lots of global variables

I have an include file with 100+ global variables. It is used in the library, but some programs to which I bind lib also need access to global variables.

How 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; 

It was difficult for me to understand why the original programmer did this, so I deleted it to define the Extern stuff. Now I think I understand the essence of TU with stackoverflow: 1 , 2 , 3 .

Now I understand that I have to define global variables in one .c file in the library and use extern in the .h file. The problem is that I do not want to duplicate the code.

Should I go back to this #define Extern voodoo?

+6
c gcc
source share
8 answers

The trick here is that the .h file is used in two different ways: it is used as a regular .h file, where all global extern characters are declared, and also used to define the global variables themselves (with no extern ). It's an ugly hack, but you can understand why someone found it necessary if you have a large number of globals (a sure sign of a very poor software design!).

In any case, there is a slightly more elegant solution - you can put all your global variables in one global structure, for example.

 // // 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 turn to the global, for example, globals.a instead of just a , which may seem inconvenient, but it may be clearer and more manageable than just having naked globals scattered throughout the code.

+8
source share

A bad template should define Extern in every .c file. Removing is probably best, but you need to somehow replace this functionality. One approach is that you can use #define in the .c file that these global variables must define. This parameter will signal .h so as not to violate global variables.

For example: A file with one .c library:

 #define FOO_LIBRARY_C #include "foo_library.h" 

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 source file (except for one) and helps reduce errors. I would also not call it Extern, as it may just cause confusion, as it may or may not be "extern"

+6
source share

Maybe I also missed something, but I ALWAYS used inclusion protection blocks in all the header files that 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; } 
+3
source share

The macro for this is stupid. Just put

 extern int myGlobal; 

in your header file and ONE .c file (usually with the same name as the .h file), put

 int myGlobal; 

No need to emphasize this level of "duplication."

+3
source share

I might be missing something, but I don't see the difference between the #define tag and just use the extern keyword.

Basically, you should declare vars in the .h file and define them in the .c file. Do not consider this a duplication of code - I think changing the point of view is the best you can do here :). You can write more lines of code, but they will be readable: D.

+2
source share

As a rule, do not use global variables. Sometimes you need to use static variables in a file, but it is best to avoid them:

  • You cannot unit test correctly encode that contains global variables
  • There is no clear separation between modules that can cause error isolation problems.
  • It is usually not thread safe. You should wrap them with mutexes, etc. If you want to use threads (usually better and better, as we get more and more cores), you may run into problems with writable general state.

Sometimes in C you cannot escape them (especially in code inherited by someone), but it is best not to release them.

As for the announcement, this may be useful in this case:

 // globals.h #ifndef GLOBALS_H #define GLOBALS_H #ifndef EXTERN #define EXTERN extern #endif EXTERN int i; #endif // globals.c #define EXTERN #include "globals.h" 
0
source share

In large programs, it is important to have one line for declaring and defining a global variable. Thus, the macro approach described above is the correct way to solve the problem.

 // globals.h #ifndef GLOBALS_H #define GLOBALS_H #ifndef EXTERN #define EXTERN extern #endif EXTERN int i; #endif // globals.c #define EXTERN #include "globals.h" 
0
source share

While this can be annoying at first, it helps you to avoid having to type text twice or forget to include something in the .c file. I have seen:

 #define FOO_C_ #include "foo.h" #include "bar.h" int foo_doit(int a, int b, int c) { ... } 

with foo.h:

 #ifndef FOO_H_ #define FOO_H_ #ifdef FOO_C_ #define GLOBAL #define DECLARE( type, name, value) type name = value #else #define GLOBAL extern #define DECLARE( type, name, value) extern type name; #endif GLOBAL int foo_doit(int a, int b, int c); GLOBAL int foo_it; // uninitialized global variable DECLARE(char, that[], "that"); // and sometimes using: #ifdef FOO_C_ char word[] = letters; #else extern char word[]; #endif #endif // FOO_H_ 
-one
source share

All Articles