我正在用 C 语言编写一个数据结构来存储命令;以下是我不满意的来源:
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "dbg.h"
#include "commandtree.h"
struct BranchList
{
CommandTree *tree;
BranchList *next;
};
struct CommandTree
{
wchar_t id; // wchar support actually has no memory cost due to the
bool term; // padding that would otherwise exist, and may in fact be
BranchList *list; // marginally faster to access due to its alignable size.
};
static inline BranchList *BranchList_create(void)
{
return calloc(1, sizeof(BranchList));
}
inline CommandTree *CommandTree_create(void)
{
return calloc(1, sizeof(CommandTree));
}
int CommandTree_putnw(CommandTree *t, const wchar_t *s, size_t n)
{
for(BranchList **p = &t->list;;)
{
if(!*p)
{
*p = BranchList_create();
if(errno == ENOMEM) return 1;
(*p)->tree = CommandTree_create();
if(errno == ENOMEM) return 1;
(*p)->tree->id = *s;
}
else if(*s != (*p)->tree->id)
{
p = &(*p)->next;
continue;
}
if(n == 1)
{
(*p)->tree->term = 1;
return 0;
}
p = &(*p)->tree->list;
s++;
n--;
}
}
int CommandTree_putn(CommandTree *t, const char *s, size_t n)
{
wchar_t *passto = malloc(n * sizeof(wchar_t));
mbstowcs(passto, s, n);
int ret = CommandTree_putnw(t, passto, n);
free(passto);
return ret;
}
这工作得很好,但我对我如何处理我的树支持的事实相当不满意wchar_t
。当我意识到填充CommandTree
会使任何小于 7 字节的数据类型花费同样多的内存时,我决定添加这个,但为了不重复代码,我CommandTree_putn
重用了 wchar_t-supporting 中的逻辑CommandTree_putnw
。
但是,由于char
and的大小不同wchar_t
,我不能只传递数组;我必须使用转换并将mbstowcs
临时传递wchar_t *
给CommandTree_putnw
. 这是次优的,因为它将CommandTree_putn
看到最多的使用,并且这将存储字符串的内存使用 ( sizeof (char)
to sizeof (char) + sizeof (wchar_t)
) 增加五倍,如果其中很多将使用较长的命令进行实例化,这可能会堆叠。
我想知道我可以做一些事情,比如创建一个包含逻辑的第三个函数,并传递 a size_t
,这取决于它将传递给它的字符串转换为 a 的值,或者void *
但假设 C 是静态类型的,我必须将逻辑转换为各自的类型,这会破坏我想要的“单个逻辑实例”的想法。const char *
const wchar_t *
s
所以最终,问题是,我是否可以只提供一次程序逻辑const char *
并const wchar_t *
分别传递包装器,而不在函数中创建一个临时wchar_t *
来处理const char *
?