0

我目前正在用 C 编写一个解析器,我在设计它时需要一个可变字符串“类”(一组对表示实例的不透明结构进行操作的函数),我称之为my_string. string 类的实例只不过是包装 a 的结构char *以及一些元数据。

但是,使用常量字符串会出现问题。例如,我有几个返回my_string *指针的方法,但有时我想返回一个常量字符串。考虑这个人为的伪代码:

my_string *element_get_data(my_element *el)
{
    if (element_has_character_data(el))
        return element_get_character_data(el); /* returns a (my_string *) */
    else
        return my_string_constant("#data");    /* ditto */
}

…在某些情况下,我想获取预构建的my_string实例,但在其他情况下,我只想返回包装在my_string结构中的字符串“#data”。

这段代码的问题是my_string每次element_get_data(...)调用它都会创建一个新的(堆分配的)实例。C 常量字符串具有很好的语义,因为它们在程序的 DATA 部分中静态分配,因此每次遇到常量字符串时,该字符串的地址总是相同的。

因此,有几个不同my_string的实例都指向完全相同的实例似乎很愚蠢char *。什么是消除重复数据的有效方法?我应该保留const char * -> my_string *映射的哈希表吗?或者有没有办法使用与 C 常量字符串类似的语义?在 Mac 上,Core Foundation 设法使用CFSTR(...)宏来做到这一点。

对我来说,理想的解决方案是以某种方式制作一个类似的宏my_string_constant(...),将my_string结构存储在程序的 DATA 部分中,因此它也可以是常量。这样的事情可能吗?

4

1 回答 1

1

当我在写这个问题时(或者更确切地说,几乎是在我完成之后),我以GNUStep 对 Core Foundation 的 CFSTR() 宏的实现的形式找到了我的问题的答案。我的类似实现如下所示:

#define MY_STR(str) ({\
    static struct { const char *buffer; my_bool shouldFree; my_bool mutable; my_bool constant; } s = {NULL, MY_FALSE, MY_FALSE, MY_TRUE};\
    s.buffer = str;\
    (my_string *)&s;\
})

这样做的原因是代码块在编译期间被内联,这意味着它创建了一个相对于本地范围的静态分配的结构。MY_STR("Hello, world!")因此,如果(例如)多次调用包含的函数,将始终返回相同的静态分配结构,从而产生我们想要的行为。

这个概念可以很容易地扩展到字符串之外,允许您轻松创建自己的静态分配对象类型。整洁的!

于 2013-02-08T04:48:51.333 回答