【问题标题】:C pointer pointer, and seg faultC 指针指针和段错误
【发布时间】:2012-08-21 17:00:40
【问题描述】:

下面是我在 C 中的简单链表。我的问题在“headRef = &newNode;”中这会导致分段错误。然后我尝试了“*headRef = newNode;”这解决了段错误问题。尽管在我看来这两行代码以相同的方式工作,但为什么一个会导致 seg 错误而另一行不会? 提前致谢。

struct node{
  int data;
  struct node* next;
};

void Push(struct node** headRef, int data){
  struct node* newNode = malloc(sizeof(struct node));
  if(!newNode) return;
  newNode->data = data;
  newNode->next = *headRef;
  headRef = &newNode;
  return;
}

【问题讨论】:

    标签: c pointers segmentation-fault


    【解决方案1】:

    您对指针的引用语义存在根本性的误解。这是核心示例:

    // Call site:
    T x;
    modify(&x);         // take address-of at the call site...
    
    // Callee:
    void modify(T * p)  // ... so the caller takes a pointer...
    {
        *p = make_T();  // ... and dereferences it.
    }
    

    所以:调用者获取地址,被调用者取消引用指针并修改对象。

    在您的代码中,这意味着您需要说*headRef = newNode;(在我们的基本示例中,您有T = struct node *)。你搞错了!

    【讨论】:

      【解决方案2】:

      newNode 已经是一个地址,您已将其声明为指针:struct node *newNode。使用*headRef = newNode,您将该地址分配给类似的指针,将struct node * 分配给struct node *。

      令人困惑的是headRef = &newNode 似乎同样有效,因为类型一致:您分配给struct node ** 另一个struct node **。

      但这是错误的,原因有两个:

      1. 您想更改函数参数headRef 的值struct node *。您已将headRef 的地址 传递给函数,因为C 是按值传递的,因此要更改变量,您需要它的地址。您要更改的这个变量是一个地址,因此您将一个指针传递给一个指针struct node **:需要额外的间接级别,以便您可以在函数内更改地址,并让该更改反映 outide 功能。因此,在函数中,您需要取消引用变量以获取您想要更改的内容:在您的函数中,您想要更改*headRef,不 headRef .
      2. 获取newNode 的地址会创建不必要的间接级别。如上所述,您要分配的值是由 newNode 持有的地址,不是 地址 newNode。

      【讨论】:

        【解决方案3】:

        headRef = &newNode是局部赋值,所以赋值只在Push函数范围内有效。如果对headRef 的更改应该在Push 之外可见,您需要执行*headRef = newNode。此外,这两者并不等价。 headRef = &newNode 将节点指针的地址分配给指向节点指针的指针,而*headRef = newNode 将节点的地址分配给指向节点的指针。

        【讨论】:

          【解决方案4】:

          您正在设置headRef 来保存位于堆栈中的变量的地址;只要你的Push() 函数返回,堆栈就不再有效,你可以指望它被覆盖。这肯定会导致段错误。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-09-18
            • 2016-02-24
            • 1970-01-01
            • 2021-05-25
            • 1970-01-01
            • 2013-04-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多