包括带有大量全局变量的C头文件

时间:2010-05-19 19:18:19

标签: c gcc

我有一个包含100多个全局变量的包含文件。它正在库中使用,但是我链接lib的一些程序也需要访问全局变量。

它的构建方式:

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

我很难理解为什么原始程序员会这样做,所以我删除了定义Extern的东西。现在我想借助stackoverflow了解TU的事情: 123

现在我明白我应该在库中的一个.c文件中定义全局变量,并在.h文件中使用extern。问题是我不想复制代码。

我应该回到那个#define外部伏都教吗?

8 个答案:

答案 0 :(得分:8)

这里的技巧是.h文件以两种不同的方式使用 - 它被用作普通的.h文件,其中所有的全局变量都被声明为extern,并且它也用于定义全局变量本身(没有extern)。这是一个丑陋的黑客,但你可以理解为什么有人觉得有必要,如果你有大量的全局变量(软件设计非常糟糕的确定迹象!)。

无论如何,有一个更优雅的解决方案 - 您可以将所有全局变量放在一个全局结构中,例如。

//
// globals.h
//

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

extern Globals globals; // declaration

-

//
// globals.c
//

#include "globals.h"

Globals globals; // definition

-

然后当你需要引用全局时,例如globals.a而不仅仅是a,这可能看起来很不方便,但这可以说比在整个代码中分散裸露的全局变量更清晰,更易于管理。

答案 1 :(得分:6)

在每个.c文件中定义Extern是一种糟糕的模式。删除它可能是最好的,但您需要以某种方式替换此功能。一种方法是您可以在.c文件中使用需要定义这些全局变量的#define。此定义将向.h发出信号,表示不是全局变量。

例如: 一个库.c文件:

#define FOO_LIBRARY_C
#include "foo_library.h"

其他.c文件:

#include "foo_library.h"

foo_library.h:

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

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

GLOBAL_PREFIX int a,b,c

这减少了在每个源文件(除一个)中定义相同内容的需要,并有助于减少错误。我也不会称它为外部因为它可能会造成混淆,因为它可能是也可能不是“外部”

答案 2 :(得分:3)

也许我也错过了一些东西,但我总是在我创建的所有头文件中使用包含警戒:

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 :(得分:3)

宏观的东西对此很愚蠢。只需加上

extern int myGlobal;

在头文件和ONE .c文件中(通常是与.h文件同名的文件),放

int myGlobal;

无需对此级别的“重复”感到压力。

答案 4 :(得分:2)

我可能会遗漏某些内容,但我发现#define内容与使用extern关键字之间没有区别。

基本上,您必须在.h文件中声明变量并在.c文件中定义它们。不要认为它代码重复 - 我认为改变观点是你可以在这里做的最好的事情:)。您可以编写更多代码行,但它们是可读的:D。

答案 5 :(得分:1)

在大型程序中,使用一行来声明和定义全局变量非常重要。因此,上述宏观方法是解决问题的正确方法。

// 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" 

答案 6 :(得分:0)

根据经验,不要使用全局变量。有时您需要在文件中使用静态变量,但最好尽量避免使用它们:

  • 您无法对包含全局变量的代码进行单元测试
  • 模块之间没有可能导致错误隔离问题的清晰分离
  • 通常线程安全。如果你想使用线程(当我们获得越来越多的内核时往往更好更好的想法),你必须用互斥体等包装它们。你可能会遇到可写共享状态的麻烦。

有时在C中你无法避免它们(特别是在某人继承的代码中),但最好是将它们排除在外。

关于声明 - 在这种情况下可能会有所帮助:

// 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"

答案 7 :(得分:-1)

虽然这一开始很烦人,但它确实可以帮助您避免两次输入内容或忘记在.c文件中包含某些内容。 我见过:

#define FOO_C_

#include "foo.h"
#include "bar.h"

int foo_doit(int a, int b, int c) {
...
}

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_