我目前正在用C编写一个解析器,在设计它时我需要的一件事是一个可变字符串“class”(一组函数对表示实例的不透明结构进行操作),我称之为{{ 1}}。字符串类的实例只不过是包含my_string
的结构体以及一些元数据。
然而,出现了一个问题,即使用常量字符串。例如,我有几个返回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
结构中的字符串“#data”。
此代码的问题在于,每次调用my_string
时,它都会创建一个新的(堆分配的)my_string
实例。 C常量字符串具有良好的语义,因为它们在程序的DATA部分中被静态分配,因此每次遇到常量字符串时,该字符串的地址始终相同。
因此,让几个不同的element_get_data(...)
个实例都指向完全相同的my_string
似乎很愚蠢。什么是重复删除这种方法的有效方法?我应该保留char *
映射的哈希表吗?或者有没有办法对C常量字符串使用类似的语义?在Mac上,Core Foundation设法使用const char * -> my_string *
宏执行此操作。
对我来说理想的解决方案将以某种方式制作一个像CFSTR(...)
这样的宏,它在程序的DATA部分存储一个my_string_constant(...)
结构,所以它也可以不变。这样的事情有可能吗?
答案 0 :(得分:1)
当我写这个问题时(或者说,在我完成后几乎立即),我以GNUStep's implementation of Core Foundation's CFSTR() macro的形式找到了我的问题的答案。我的类似实现如下所示:
#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!")
的函数,则将始终返回相同的静态分配结构,从而产生我们期望的行为。
这个概念可以很容易地扩展到字符串以外的东西,允许您轻松创建自己的静态分配对象类型。整齐!