C pointer pointer, and seg fault

萝らか妹 提交于 2020-01-21 19:22:12

问题


Below is my simple linked list in C. My question is in "headRef = &newNode;" which causes segmentation fault. Then I tried instead "*headRef = newNode;" which resolves the seg fault problem. Though the two lines of code seem to me to work in the same way, why is one causing seg fault and the other one not? Thanks in advance.

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

回答1:


You have a fundamental misunderstanding of reference semantics via pointers. Here's the core example:

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

So: Caller takes address-of, callee dereferences the pointer and modifies the object.

In your code this means that you need to say *headRef = newNode; (in our fundamental example, you have T = struct node *). You have it the wrong way round!




回答2:


newNode is already an address, you've declared it as a pointer: struct node *newNode. With *headRef = newNode you're assigning that address to a similar pointer, a struct node * to a struct node *.

The confusion is that headRef = &newNode appears to be similarly valid, since the types agree: you're assigning to a struct node ** another struct node **.

But this is wrong for two reasons:

  1. You want to change the value of your function argument headRef, a struct node *. You've passed the address of headRef into the function because C is pass-by-value, so to change a variable you'll need it's address. This variable that you want to change is an address, and so you pass a pointer to a pointer, a struct node **: that additional level of indirection is necessary so that you can change the address within the function, and have that change reflected outide the function. And so within the function you need to dereference the variable to get at what you want to change: in your function, you want to change *headRef, not headRef.
  2. Taking the address of newNode is creating an unnecessary level of indirection. The value that you want to assign, as mentioned above, is the address held by newNode, not the address of newNode.



回答3:


headRef = &newNode is a local assignment, so the assignment is only valid within the scope of Push function. If changes to the headRef should be visible outside the Push you need to do *headRef = newNode. Furthermore, these two are not equivalent. headRef = &newNode assigns the address of a node pointer to a pointer to node pointer while the *headRef = newNode assigns the address of a node to a pointer to a node using indirection.




回答4:


You're setting headRef to hold the address of a variable that lives on the stack; as soon as your Push() function returns, the stack is no longer valid and you can count on it getting overwritten. This is a sure recipe for a segfault.



来源:https://stackoverflow.com/questions/12059663/c-pointer-pointer-and-seg-fault

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!