0

有没有人可以解释以下代码。我对双指针有疑问,无法理解代码是如何链接的。

int remove_person(Post **list, char *name)
    {
        Post *p = *list;
        if(strcmp(p->name, name) == 0)
        {
            free(*list); //rensar minnet
            *list = p->next;
            return 1;  
        }
        for(; p->next != NULL; p = p->next)
        {
            if(strcmp(p->next->name, name) == 0)
            {
                Post *tmp = p->next;
                p->next = p->next->next;
                free(tmp); //rensar minnet 
                return 1;
            }
        }

        return 0;
    }
4

3 回答 3

4

没有什么好理解的。代码是错误的。

 // at this point *list and p _could_ be NULL

Post *p = *list;
  // At this point, *list and p point to the same object

if(strcmp(p->name, name) == 0)
    {  //   ^^^^--------------- WRONG: if p is NULL, dereferencing is not allowed

    free(*list); 
        // at this point the object has been destroyed

    *list = p->next; // .. and referenced AFTER ITS DESTRUCTION
           // ^^^^ <<------- WRONG
    return 1;  
    }

第一个块*list = p->next;中的语句引用了一个刚刚被释放的对象内的指针(并指向同一个对象)。代码也过于复杂。(请在此处查看我的答案以获取正确(且简单!)的方法)if(strcmp(...) == 0) { }*listp*list

以正确顺序执行操作的简单修复方法是:

Post *p = *list;
if(p && strcmp(p->name, name) == 0)
    {
       *list = p->next;
       free(p); //rensar minnet
       return 1;  
    }

但是一个不包含特殊情况且不重复条件和代码块的最小版本将是:

int remove_person(Post **list, char *name)
{
    Post *del;
    for(; (del = *list); list = &(*list)->next) {
        if( strcmp(del->name, name) ) continue;

        *list = del->next;
        free(del); //rensar minnet 
        return 1;
    }

    return 0;
}
于 2013-10-02T08:34:49.513 回答
2

这是指针指针的一个相当简单的用法:该函数从单链表中删除一个元素,并且如果删除的元素是第一个元素,则能够修改“头”指针。

于 2013-10-02T08:09:32.647 回答
0

由于 C 是按值传递的,为了使作为参数传递的指针的修改保持在函数范围之外,作者决定使用双指针习语。

如果您要list直接作为指针传递,则您所做的任何修改都不会在函数范围之外可见,除非您要返回该指针(并更改函数的返回类型)。

但是由于int返回表示成功/失败,这不是一个选项

于 2013-10-02T08:12:22.773 回答