2

所以这是我要解决的问题,我正在用 C 编程。

我们有一个可以为您初始化结构的函数。

typedef struct {
  int val1;
  int val2;
} custom_t;

custom_t init_custom() {
  custom_t temp;

  temp.val1 = 5;
  temp.val2 = 5;


  return temp;
}

你会像这样使用它:

custom_t some_name = init_custom();

我有 4 个以 custom_t 作为输入的函数,可以用它做一些工作。

在另一个文件中,我有很多将在多线程环境中运行的库函数。无论线程如何,这些库函数都需要在同一个 custom_t 变量上工作。

库函数不会将 custom_t 变量传递给它,因为目标是另一个用户应该能够在不考虑 custom_t 变量的情况下使用库函数。

我在想我必须在定义库函数的命名空间中使 custom_t 变量成为全局变量,但我错误地说全局变量必须是 const。

我不确定如何实现这一目标,我将不胜感激我能得到的所有帮助。如果我的解释不够好,请随时提出任何问题,我会尽力详细说明。

编辑:修复了变量初始化错字

4

2 回答 2

3

随着custom_t = init_custom();您尝试设置类型名(即custom_t)。

就叫它别的吧:

custom_t my_global_custom = init_custom();

但是,要从多个线程和库函数中访问它,假设您需要写入它,您需要将对此的访问包装在互斥锁中:

pthread_mutex_t custom_mutex = PTHREAD_MUTEX_INITIALIZER;
custom_t my_global_custom;

my_global_custom = init_custom();

// how each thread must access it
pthread_mutex_lock(&custom_mutex);
func_that_uses_my_global_custom();
pthread_mutex_unlock(&custom_mutex);

更新:

我的示例并不是字面意义上的初始化程序,而是一个赋值

pthread_mutex_t custom_mutex = PTHREAD_MUTEX_INITIALIZER;
custom_t my_global_custom;
custom_t my_global_2;

custom_t
init_custom(void)
{
    custom_t temp;

    temp.val1 = 5;
    temp.val2 = 5;

    return temp;
}

void
init_custom2(custom_t *temp)
{

    temp->val1 = 5;
    temp->val2 = 5;
}

int
main(void)
{

    // either one of these should work ..
    my_global_custom = init_custom();
    init_custom2(&my_global_2);

    // start some threads ...

    return 0;
}

void *
thread_func(void *)
{

    // how each thread must access it:
    pthread_mutex_lock(&custom_mutex);
    func_that_uses_my_global_custom();
    pthread_mutex_unlock(&custom_mutex);

    return (void *) 0;
}

更新#2:

但是您知道在主函数之外初始化 my_global_custom 的任何方法吗?或者那是不可能的?

gcc[至少]另一种方法是创建一个构造函数。鉴于上述函数和定义,将 init 调用移至:

void __attribute__((constructor))
my_global_constructor(void)
{

    my_global_custom = init_custom();
    init_custom2(&my_global_2);
}

没有什么需要[也不应该]调用这个函数。它会在被调用之前 main被自动调用,因为它现在是一个特殊的函数。

这些通常由想要进行一些初始化的库使用,但不想承担必须知道调用的负担(例如) 这种情况下,它在库的“正确”时间被调用[基于链接, ETC。]。maininit_liba(); init_libb(); ...

还有一个__attribute__((destructor))比可以用来“破坏”东西[main返回后,IIRC]。

有关这方面的更多信息,请参阅:__attribute__((constructor)) 究竟是如何工作的?

就个人而言,我现在使用上面的属性,但是,为了怀旧,我喜欢旧的.init/.fini部分。

于 2016-08-24T22:39:35.360 回答
1

正如您在@CraigEstey 的回答中所阐明的那样,问题不在于变量需要是const,而是它的初始化程序需要是编译时常量。解决此类问题的一种方法是通过宏定义静态初始化值,而不是作为函数返回值。例如,在一些适当的头文件中声明

typedef struct {
    int val1;
    int val2;
} custom_t;

#define CUSTOM_T_INITIALIZER { .val1 = 5, .val2 = 5 }

然后,您可以custom_t像这样初始化类型的变量:

custom_t some_name = CUSTOM_T_INITIALIZER;

,包括在文件范围内。

更新:

如果您需要为不是编译时常量的文件范围或静态持续时间变量分配一个值(包括如果它具有聚合类型并且其成员之一所需的值不是编译时常量),那么您不能为此目的使用初始化程序。相反,您必须安排在程序启动后将所需的值分配给该变量,可能是通过调用某种初始化函数。

于 2016-08-24T22:57:08.250 回答