我想静态初始化一个结构,该结构将从包含一些标题的所有文件中可见。
实际的目的是运行在编译时指定的函数列表,这就是我想静态初始化的原因。我想把它们所属的列表放在声明或定义它们的文件中。
已举例:
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()); ... }
有更好的方法吗?
答案 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
,以简化初始化。