我有自己的 C hash_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_name创建2个hash_maps - > key_code 映射和 flag_name - > flag_code 映射。问题是我不希望每次调用请求处理程序函数时都创建此标志,但是在第一次调用函数时只有一个数据结构实例,并且在连续的函数调用中我想重用这个数据结构(数据存储)已创建。
我的hash_map是在堆上创建的,所以不可能像在库源代码文件中的某个地方那样分配它。
在Java甚至C ++中,我可以创建一些Singleton模式或静态成员,但这种概念在C语言中不可用。可能我可以在程序开始的某个地方的程序启动时创建这个hash_map但是我怎样才能将引用传递给程序使用的库。
我最近的想法是使用static hash_map_t variable inside my handle_keyboard_input function
并且仅在它为NULL(第一个函数调用)时以某种方式初始化它,并且如果在连续调用中变量不是NULL,则只重用先前初始化的hash_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);
}
答案 0 :(得分:1)
由于这似乎是一个库,因此您有以下几种选择:
您可以使您的库更“面向对象”并强制用户进行正确的实例化。例如,您将ADT struct defined作为KeyboardHandler
,然后您的handle_keyboard_input
会看起来像这样:
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);
可以为both Windows and POSIX dll创建库初始值设定项。所以你可以自动完成这项工作。
否则,在您的函数想要使用这个可能未初始化的哈希表时,您似乎必须进行“检查”(可能它是单个函数,但无论如何)。在这种情况下,我至少会将它重构为一个单独的函数:
void handle_keyboard_input(char **tokens, size_t num_tokens) {
initialize_hashes_if_needed();
// ...and then the rest of the function
}
理由是如果您认为还有其他东西需要进行malloced,您不希望修改多个功能。
答案 1 :(得分:0)
是的,上面的代码会导致指针只被初始化一次(或者如果你将它们设置为NULL
,条件将是true
并且它将再次初始化)并保留在内存中即使你得到功能之外。
函数static
变量的生命周期在程序流第一次遇到声明时开始,并在程序终止时结束 - 换句话说,它们是全局变量。
此变量的名称只能在函数中访问,并且没有链接。
如果您认为需要全局可访问的变量,仍需要非常小心。 Read here
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);
}