模仿C中的静态对象的构造函数

时间:2011-10-21 11:33:14

标签: c++ c constructor

我希望有一个全局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做到吗?

5 个答案:

答案 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 ++)。