Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
“有效地”;“包装”;C中的常量字符串_C - Fatal编程技术网

“有效地”;“包装”;C中的常量字符串

“有效地”;“包装”;C中的常量字符串,c,C,我目前正在用C编写一个解析器,在设计它时,我需要一个可变字符串“类”(一组在表示实例的不透明结构上操作的函数),我称之为my_string。string类的实例只不过是包装了char*以及一些元数据的结构 但是,对于常量字符串,出现了一个问题。例如,我有几个方法返回my_string*指针,但有时我想返回一个常量字符串。考虑这个伪代码: my_string *element_get_data(my_element *el) { if (element_has_character_data

我目前正在用C编写一个解析器,在设计它时,我需要一个可变字符串“类”(一组在表示实例的不透明结构上操作的函数),我称之为
my_string
。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
实例,但在其他情况下,我只希望返回包装在
my_string
结构中的字符串“#data”

此代码的问题在于,每次调用
元素get\u data(…)
时,它都会创建一个新的(堆分配的)
my\u string
实例。C常量字符串有很好的语义,因为它们是在程序的数据部分静态分配的,所以每次遇到常量字符串时,该字符串的地址总是相同的

因此,让几个不同的
my_string
实例都指向完全相同的
char*
似乎很愚蠢。消除重复数据的有效方法是什么?我应该保留
const char*->my_string*
映射的哈希表吗?或者有没有一种方法可以使用与C常量字符串相似的语义?在Mac上,核心基金会用<代码> CFSTR(…)<代码>宏> < /P>来管理这一点。
对我来说,理想的解决方案是以某种方式创建一个宏,如
my_string\u constant(…)
,它将
my_string
结构存储在程序的数据部分,因此它也可以是常量。这样的事情可能吗?

当我写这个问题时(或者更确切地说,几乎是在我写完之后),我发现问题的答案是。我的类似实现如下所示:

#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!”)
的函数被多次调用,那么将始终返回相同的静态分配结构,从而产生我们想要的行为


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

拥有哈希表的一个好处是,只需一个引用计数器,就可以将字符串的副本保留为单个字符串。此外,如果您正在编译的程序有两个相同但位于源代码中不同位置的字符串文字,那么表中仍然只有一个条目。