【问题标题】:Imitating constructor of static objects in C在C中模仿静态对象的构造函数
【发布时间】:2011-10-21 11:33:13
【问题描述】:

我想要一个全局的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 保存全局变量。如果有人链接到使用libnameslibnameuser,它会自动将libnameuser 中定义的所有名称添加到libnames 中的names 数组中。

有什么办法吗?

在 C++ 中,我可以将 names[names_len++] = "..." 插入到全局对象的构造函数中,并且必须调用它。但是我可以用普通的 C 来做到这一点吗?

【问题讨论】:

    标签: c++ c constructor


    【解决方案1】:

    如果你使用 gcc,你可以使用构造函数属性__attribute__((constructor)) 来获得相同的效果。然而,这是非标准的 C。

    但是我建议不要使用这种模式,因为在 main 之前运行的任何函数的顺序都无法控制。在 main 开始运行后,我宁愿找到一种很好的方法来挂钩所有“构造函数”。

    【讨论】:

    • 我不介意顺序。我会很高兴听到实现类似目标的更好模式。我想尽可能地让用户感到轻松。
    【解决方案2】:

    更新:有关此答案的更新版本,请参阅 https://stackoverflow.com/a/2390626/270788

    下面是一个预处理器抽象,用于支持 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】:

    如果您不是 100% 关心可移植性并且可以保证 GCC,那么您可以使用 GCC 中的“构造函数”属性来做您想做的事情。见:http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Function-Attributes.html

    不过,我同意@Anders K 的观点,他说您应该将这种行为封装在函数中。

    【讨论】:

      【解决方案4】:

      我认为为了实现您想要的效果,最好为您的 names[] 数组创建几个包装函数。然后访问您的“全局”名称数组的模块必须通过该接口。

      这将允许您更好地控制和解耦

      然后您可以将数组放在一个模块中,然后在标题中公开这些函数,但保持数组隐藏。

      【讨论】:

      • 但问题仍然存在:如何从库代码中自动执行这些函数?
      • @MagnusHoff 说了什么。我的问题不是阻止访问names,而是强制用户在访问我的库之前更新names
      【解决方案5】:

      我认为全局变量的初始化也适用于 C。

      int func1();
      int someGlobalVariable = func1();
      
      int func1()
      {
          /* Your initialization code can go here */
      } 
      

      我希望我没有误会这在 C 中工作(很长时间以来一直只使用 C++)。

      【讨论】:

        猜你喜欢
        • 2011-07-16
        • 2012-12-26
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        相关资源
        最近更新 更多