我希望有一个全局names
变量,看起来像
char* names[NAMES_CAP];
int names_len = 0;
我希望每个链接到此库的人都能够将一个项目添加到此列表中。
从main
开始很容易。
int main(int argc,char**argv) {
names[names_len++] = "new name";
names[names_len++] = "new name 2";
}
但如果我想要堆叠两个库怎么办? (即,我的库,libnames
包含全局变量。如果有人链接到使用libnameuser
的{{1}},它会自动将libnames
中定义的所有名称添加到{ {1}}中的{1}}数组。
有没有办法做到这一点?
在C ++中,我可以将libnameuser
插入到全局对象的构造函数中,并且必须调用它。但我可以用普通的C做到吗?
答案 0 :(得分:4)
如果您使用的是gcc,则可以使用构造函数属性__attribute__((constructor))
来获得相同的效果。然而,这是非标准的C.
然而,我会建议不要使用此模式,因为无法控制在main之前运行的任何函数的排序。在main开始运行之后,我宁愿在所有“构造函数”函数中找到一个很好的挂钩方法。
答案 1 :(得分:2)
如果您不是100%关注可移植性并且可以保证GCC,那么您可以使用GCC中的“构造函数”属性执行您想要的操作。请参阅:http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Function-Attributes.html。
但是,我同意@Anders K,他说你应该将这种行为封装在函数中。
答案 2 :(得分:2)
更新:有关此答案的更新版本,请参阅https://stackoverflow.com/a/2390626/270788。
下面是一个预处理器abstration,用于支持GCC和MSVC的C静态初始化函数。 GCC版本也可以与LLVM CC一起使用,也可以使用其他一些编译器。
MSVC版本通过将ptr放置在由应用程序或DLL启动代码处理的特殊部分中的静态初始化函数来工作。
#if defined(__GNUC__)
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#elif defined(_MSC_VER)
#define INITIALIZER(f) \
static void __cdecl f(void); \
__declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
static void __cdecl f(void)
#endif
INITIALIZER(initializer_1) { names[names_len++] = "new name"; }
INITIALIZER(initializer_2) { names[names_len++] = "new name 2"; }
答案 3 :(得分:1)
我认为为了达到你想要的效果,最好为你的names []数组创建一些包装器函数。然后访问“全局”名称数组的模块必须通过该接口。
这将允许您更好地控制和解耦
然后,您可以将数组放在一个模块中,然后在标头中公开这些函数,但保持数组隐藏。
答案 4 :(得分:0)
我认为全局变量的初始化也适用于C.
int func1();
int someGlobalVariable = func1();
int func1()
{
/* Your initialization code can go here */
}
我希望我不会误以为在C中工作(现在很长时间以来只使用C ++)。