【问题标题】:C pointer to pointer skiss [closed]C指针指向指针滑雪[关闭]
【发布时间】:2013-10-02 08:04:13
【问题描述】:

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

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;
    }

【问题讨论】:

  • "skiss"?!?这是什么意思?是英文还是错字?
  • 1 不要说它是双指针,而是正确的词是“指向指针的指针”第二个你有未定义的行为(由 wildplasser 回答)

标签: c pointers


【解决方案1】:

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

 // 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;  
    }

第一个if(strcmp(...) == 0) { } 块中的*list = p-&gt;next; 语句引用了一个刚刚被释放的对象*list 内的指针(p*list 指向同一个对象) .代码也过于复杂。 (请参阅我的回答 here 以获得正确(且简单!)的方法)

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

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;
}

【讨论】:

  • 这很好。将指针保持在循环中,始终指向指向当前对象的指针,就完美了。只是一件事,我建议明确地说 if( strcmp(dell-&gt;name, name) != 0 ) continue; 因为 strcmp 很容易与返回布尔值的东西混淆。
  • 这是风格问题。我更喜欢省略!= 0,因为它不是必需的(语言的int --&gt; pseudo-boolean 推广暗示了它)而且使用C 超过一周的人会知道@987654333 的行为@
  • 更多的是可读性而不是需要。在测试一个应该包含伪布尔值的变量时,我省略了!= 0,但在大多数其他情况下明确写它,尤其是strcmp,因为我不止一次被烧毁。请记住,原始发布者可能是初学者,可能会犯这种错误。
  • 我不是初学者,我更喜欢以自己的风格写作。在表达式中添加不必要的 != 0 术语只会增加视觉混乱的数量。就个人而言,我从来没有被strcmp() 咬过。零只有一个值,对我来说将它用作is_equal 的返回值是非常有意义的,因为只有一种相等的方式(并且不止一种不同的方式)
  • 如果你打算用 C 编程,你应该了解它的根源。在编写高度可移植代码 (C90) 的任何人都使用的 C 风格中,它没有布尔值,因此没有什么可混淆的问题。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 2017-05-13
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      相关资源
      最近更新 更多