C:使用外部链接初始化全局常量

时间:2013-10-31 13:03:23

标签: c initialization extern

我想静态初始化一个结构,该结构将从包含一些标题的所有文件中可见。

实际的目的是运行在编译时指定的函数列表,这就是我想静态初始化的原因。我想把它们所属的列表放在声明或定义它们的文件中。

已举例:

general.h中:

struct Widget { int (*a)(); };

foo.h中:

int oof1(void);
int oof2(void);

foo.c的:

#include "foo.h"

int oof1(void) { return 1; }
int oof2(void) { return 2; }

struct Widget foo_widgets[] = { {oof1}, {oof2} };

bar.c:

#include "foo.h"
#include "baz.h"

struct Widget *foo_widgets;
struct Widget *baz_widgets;

struct WidgetsContainer {
    struct Widget *widget_list;
} wlists[] =
    {
        { foo_widgets },
        { baz_widgets }
    };

void usage(void) { ... ; process (wlists[i].widget_list); ... }

这显然不起作用,因为“初始化元素不是常量” - 这是因为当编译器正在翻译bar.c时,它认为它不知道foo_widgets(或bar_widgets)的位置。

但是因为bar.c #include foo.h无论如何,它总是与foo.c一起编译:

gcc foo.c baz.c bar.c

所以我希望有一种方法可以在源代码中反映这一点。

我无法在foo.h中声明foo_widgets,因为如果不多次定义它,我将无法初始化它(因为foo.h包含在多个文件中)。

不合理的解决方法

foo.h中:

...

Widget *get_foos(void) { return foo_widgets; }

bar.c:

...

struct Widget_lists {
    struct Widget (*widget_list)();
} wlist[] =
    {
        { get_foos },
        { get_bazes }
    };

void usage(void) { ...; process(wlist[i].widget_list()); ... }

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

您希望拥有一个可以在任何地方访问的全局变量...为此,您必须在相应的标题中将其声明为外部变量。

这里应该按如下方式进行:

在foo.h中:

/* ... */
int oof1(void);
int oof2(void);
extern int (*foo_widget)(void)[2];

在foo.c中:

int (*foo_widget)(void)[2] = {{oof1}, {oof2}};

通过这样做,当包含“foo.h”时,foo_widget变量将是已知的(并且预计在其他地方定义 - 在foo.c中 - )。< / p>

更准确地说...... 需要使用foo_widget的任何代码必须在某处包含行extern int (*foo_widget)(void)[2];,无论是在包含的标题中(更聪明的方式)或只是 .c 文件开头的一行。

当然,如果您事先无法知道可以拥有的小部件数量,则可能需要动态数据结构,例如链表或树(如果可能,请进行排序和平衡;))来存储它们。 extern变量很可能是在需要时动态分配的常规指针。但定义行仍然需要 ,因此在这种情况下,您可能会在相应的源文件中使用struct my_struct *pointer = NULL;

注意:我可以自由地使用通用函数指针替换struct Widget,以简化初始化。