在C中使用hashmap存储字符串-整数映射一次并用于整个程序运行

在C中使用hashmap存储字符串-整数映射一次并用于整个程序运行,c,static,hashmap,C,Static,Hashmap,我有自己的C hash\u map\t struct实现,我可以如下使用 // string value allocator allocator_t *str_value_allocator; allocator_init(&str_value_allocator, string_allocate_handler, string_deallocate_handler); str_hash_map_init(&str_hash_map, str_value_allocator,

我有自己的C hash\u map\t struct实现,我可以如下使用

// string value allocator

allocator_t *str_value_allocator;
allocator_init(&str_value_allocator, string_allocate_handler, string_deallocate_handler);
str_hash_map_init(&str_hash_map, str_value_allocator, 5);

str_hash_map_put(str_hash_map, test_key, test_val, strlen(test_val));
str_hash_map_get(str_hash_map, test_key, NULL)
str_hash_map_remove(str_hash_map, test_key)

str_hash_map_free(str_hash_map);
我想在如下函数中使用此哈希映射:

void handle_keyboard_input(char **tokens, size_t num_tokens) {

    char *virtual_key_name = strtok(tokens[1], " ");
    size_t num_flags = 0;
    char **modifier_flags = str_split(tokens[2], ", ", &num_flags);

    // map virtual_key_name (char *) to virtual_key code (int) 
    // foreach modifier flag (char *) map to modifier flag code (int) 
}
我可以为key\u name->key\u code映射和flag\u name->flag\u code映射创建两个哈希映射。问题是,我不希望每次调用请求处理程序函数时都创建此标志,但在函数的第一次调用中只有一个数据结构实例,并且在后续函数调用中,我希望重用已经创建的数据结构(数据存储)

我的hash_映射是在堆上创建的,因此不可能像库源代码文件中的数组那样分配它

在java或C++中,我可以创建一些单独的模式或静态成员,但是这种概念在C语言中是不可用的。也许我可以在程序启动时在程序开始时的某个地方创建这个hash_映射,但如何传递对程序使用的库的引用呢

我最近的想法是在我的handle\u keyboard\u input函数中使用
静态hash\u map\t变量
,并且只有在它为NULL时(第一次函数调用)才以某种方式初始化它,如果变量在连续调用中不为NULL,只需重用以前初始化的hash\u map\t结构

解决这个问题的最佳方法是什么

更新

我可以使用这样的代码吗

static str_hash_map_t *virtual_keys_map = NULL;
static str_hash_map_t *modifier_flags_map = NULL;

if (virtual_keys_map == NULL) {
    virtual_keys_map_init(&virtual_keys_map);
}

if (modifier_flags_map == NULL) {
    modifier_flags_map_init(&modifier_flags_map);
}

是的,上面的代码会导致指针只初始化一次(或者,如果您将指针设置为
NULL
,则条件将为
true
,并且它将再次初始化),并且即使在函数外部,指针仍会保留在内存中

函数
静态
变量的生存期从程序流第一次遇到声明时开始,在程序终止时结束-换句话说,它们是全局变量

此外,此变量的名称只能在函数中访问,并且没有链接

如果您认为您需要一个全局可访问的变量,仍然需要非常小心


由于这似乎是一个库,因此您有几个选项:

  • 您可以使您的库更加“面向对象”,并强制用户执行正确的实例化。例如,您将使用as
    键盘处理程序
    ,然后您的
    键盘处理输入
    将改为如下所示:

    void KH_handle_input(KeyboardHandler self, char **tokens, size_t num_tokens);
    
    这意味着调用方现在负责对单个部分进行实例化:

    // caller must get the ADT instance at some point, and you don't care when
    KeyboardHandler kh = KH_init();
    KH_handle_input(kh, some_tokens, num_tokens);
    
    // some other part can be initialized later
    MouseHandler mh = MH_init();
    MH_handle_input(mh, some_tokens, num_tokens);
    
  • 可以为DLL创建库初始值设定项。所以你可以让它自动完成

  • 否则,在函数想要使用这个可能未初始化的哈希表(可能是单个函数,但无论如何)的任何时候,似乎都必须进行此“检查”。在这种情况下,我至少会将其重构为一个单独的函数:

    void handle_keyboard_input(char **tokens, size_t num_tokens) {
        initialize_hashes_if_needed();
        // ...and then the rest of the function            
    }
    
    原因是,如果您决定还有其他一些功能需要进行malloced,那么您不想修改多个函数


  • 函数中的静态(指针)变量也是单例变量。或者,更简单的是,一个全局变量。所以我可以使用更新部分中的代码?在启动时分配这些结构有什么问题?在调用每个单独的函数之前检查NULL是没有意义的。如果您想自动执行此操作,dll库也可以公开init函数。这是Cocoa应用程序使用的C库,它启动服务器,然后处理请求,如果有特定类型的请求,则调用函数,然后我应该使用此哈希映射。我不知道如何轻松地启动这个hashmap(服务器启动),然后使用它。我是否应该将此结构设置为全局结构并在某个地方启动它?如何访问此指针?
    void handle_keyboard_input(char **tokens, size_t num_tokens) {
        initialize_hashes_if_needed();
        // ...and then the rest of the function            
    }