2

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

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

人为的例子:

一般.h:

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

富.h:

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

富.c:

#include "foo.h"

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

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

酒吧.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 #includes foo.h 无论如何,它总是与 foo.c 一起编译:

gcc foo.c baz.c bar.c

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

我不能foo_widgets在 foo.h 中声明,因为这样我就无法在不多次定义的情况下对其进行初始化(因为 foo.h 包含在多个文件中)。

不优雅的解决方法

富.h:

...

Widget *get_foos(void) { return foo_widgets; }

酒吧.c:

...

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

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

有没有更好的办法?

4

1 回答 1

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 中 - )。

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

当然,如果您无法提前知道您可以拥有的小部件的数量,您可能需要一个动态数据结构,例如链表或树(如果可能,有序和平衡;))来存储它们。该extern变量很可能是在需要时动态分配的常规指针。但是仍然需要定义行,所以在这种情况下,您可能在适当的源文件中有类似的东西。struct my_struct *pointer = NULL;

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

于 2013-10-31T13:14:05.673 回答