递归struct和malloc()

时间:2011-11-27 18:17:02

标签: c struct malloc recursive-datastructures

我有一个递归struct,它是:

typedef struct dict dict;
struct dict {
    dict *children[M];
    list *words[M];
};

以这种方式初始化:

dict *d = malloc(sizeof(dict));
bzero(d, sizeof(dict));

我想知道bzero()在这里究竟做了什么,以及我如何以递归方式为孩子们malloc()

修改:我希望能够malloc() childrenwords

void dict_insert(dict *d, char *signature, unsigned int current_letter, char *w) {
    int occur;
    occur = (int) signature[current_letter];
    if (current_letter == LAST_LETTER) {
        printf("word found : %s!\n",w);
        list_print(d->words[occur]);
        char *new;
        new = malloc(strlen(w) + 1);
        strcpy(new, w);
        list_append(d->words[occur],new);
        list_print(d->words[occur]);
    }
    else {
        d = d->children[occur];
        dict_insert(d,signature,current_letter+1,w);
    }
}

3 个答案:

答案 0 :(得分:2)

bzero(3)将内存初始化为零。它相当于使用第二个参数0调用memset(3)。在这种情况下,它将所有成员变量初始化为null指针。 bzero被视为已弃用,因此您应将其替换为memset;或者,您只需拨打calloc(3)而不是malloc,这会在成功后自动将退回的内存清零。

你不应该使用你用C编写的两个强制转换中的任何一个,void*指针可以隐式地转换为任何其他指针类型,任何指针类型都可以隐式强制转换为void*malloc会返回void*,因此您只需将其分配给dict *d变量,而无需投射。同样,bzero的第一个参数是void*,因此您可以直接将d变量直接传递给它而无需强制转换。

要理解递归,首先必须了解递归。如果你想避免无限分配内存,请确保你有一个合适的基本案例。

答案 1 :(得分:1)

bzero只是将内存归零。 bzero(addr, size)基本上等同于memset(addr, 0, size)。至于为什么你要使用它,从我所看到的大约一半时间使用它,这只是因为有人虽然把记忆归零似乎是一个好主意,即使它没有真正完成任何事情。在这种情况下,效果似乎是将一些指针设置为NULL(虽然它不是完全可移植的)。

要递归分配,您基本上只是跟踪当前深度,并分配子节点,直到达到所需深度。在此订单上编写代码可以完成这项工作:

void alloc_tree(dict **root, size_t depth) { 
    int i;
    if (depth == 0) {
        (*root) = NULL;
        return;
    }

    (*root) = malloc(sizeof(**root));

    for (i=0; i<M; i++)
        alloc_tree((*root)->children+i, depth-1);       
}

我应该补充一点,我无法想象这样做的递归分配。在典型情况下,您插入数据,并根据需要分配新节点以保存数据。具体细节取决于你是否(如果是这样)保持树平衡。对于像这样的多路树,使用一些B树变体是相当普遍的,在这种情况下,上面给出的代码通常根本不适用 - 使用B树,填充节点,当它达到极限时,将其分成两半并将中间项目提升为父节点。当它到达树的顶部并且根节点已满时,您分配一个新节点。

答案 2 :(得分:1)

通常,当您不确定编译器为您生成了什么时,最好使用printf来报告结构的大小。在这种情况下,dict的大小应该是指针大小的2 * M *。在这种情况下,bzero将用零填充一个字典。换句话说,子元素和单词数组的所有M元素都将为零。

为了初始化结构,我建议创建一个函数,它接受一个指向dict的指针和每个子节点的malloc,然后调用它自己来初始化它:

void init_dict(dict* d)
{
    int i;
    for (i = 0; i < M; i++)
    {
        d->children[i] = malloc(sizeof(dict));
        init_dict(d->children[i]);

        /* initialize the words elements, too */
    }
}
如果你能看到为什么这段代码不能正常工作,那么

+1给你。 (提示:它有一个无限的递归错误,需要一个规则来告诉它子树需要多深才能停止递归。)