如何使用某些逻辑初始化全局?

时间:2019-07-13 13:26:40

标签: c global

我需要创建一个对象,该对象将用于程序的其余部分。因此,它必须是全球性的。但是,它的值必须是某种逻辑的结果(调用某些函数)。推荐的方法是什么?

我能想到的方法是:

MyThing my_global;
bool my_global_is_initialized = false;

void some_function_using_the_global(void) {
    if (!my_global_is_initialized) {
        my_global = initialize_global();
    }

    do_stuff_with_global();
}

这种方法是否有问题?有更好的方法吗?

4 个答案:

答案 0 :(得分:5)

有几种方法可以做到这一点:

  1. main的开头进行初始化。

  2. 仅公开函数MyThing *get_global(void)。然后,全局变量的用户将调用此函数以获得指针。该函数可以执行所需的任何操作,包括在首次调用它时初始化静态变量:

    MyThing *get_global(void) {
        static MyThing my_global;
        static bool is_initialized = false;
    
        if (!is_initialized) {
            my_global = initialize_global();
            is_initialized = true;
        }
        return &my_global;
    }
    

    ((如果需要,您可以在宏#define MyGlobal (*get_global())后面隐藏此功能的使用,类似于errno的实现方式。)

  3. 某些系统提供了用于启动时自动调用功能的非标准功能,例如__attribute__((constructor)) in gcc

      

    constructor属性使函数在执行进入main ()之前自动被调用。

答案 1 :(得分:3)

您的好方法。我还要标记static

您为标志检查付出了很小的运行时间开销,但这可能不是问题(函数调用开销可能会花费更多)。

或者,您可以拥有一个library_init函数(占位符名称;选择您自己的函数),您需要用户在使用函数之前调用该函数。

不重要的是,在clang / gcc上有__attribute((__constructor__)),其工作方式类似于library_init,但在程序/库加载时自动完成。

答案 2 :(得分:0)

如果它是一个全局变量,那么您正在做的是一个反模式,除非存在MyThing的多个全局实例,并且在这种情况下有多个标志,每个全局变量甚至更糟。

如果MyThing等同于基本的C型,则只需使用超出您的用例范围的值来表示未初始化。

如果是结构,则将初始化标志放在结构内。

如果它是API的一部分,并且您要确保API的用户未修改全局变量,则必须注意使MyThing不透明。

答案 3 :(得分:-2)

我不能完全确定'MyThing'是什么类型的对象以及可以使用什么初始化该全局变量的值,但是如果您知道例如,initialize_global()函数将永远不会使用该对象初始化'my_global'值(-1),则可以删除多余的全局变量,然后执行以下操作:

    #define MYTHING_UNINITIALIZED (-1)

    MyThing my_global = MYTHING_UNINITIALIZED;

    void some_function_using_the_global(void) {
        if (MYTHING_UNINITIALIZED == my_global) {
            my_global = initialize_global();
        }

        do_stuff_with_global();
    }