ani*_*mar 1 c pointers structure
鉴于以下结构:
struct node
{
int data;
struct node *next;
};
Run Code Online (Sandbox Code Playgroud)
以下两个功能有什么区别:
void traverse(struct node *q);
Run Code Online (Sandbox Code Playgroud)
和
void traverse(struct node **q);
Run Code Online (Sandbox Code Playgroud)
他们是如何使用的?
一个采用指向节点的指针:
void traverse(struct node *q);
Run Code Online (Sandbox Code Playgroud)
另一个是指向节点的指针(注意函数的名称更改).
void insert(struct node **q);
Run Code Online (Sandbox Code Playgroud)
当您需要访问指向的内容时,将使用前者.当您需要访问指向的内容时使用后者,即您可能需要将来自调用方的实际指针变量修改为潜在的输入和输出参数.
前者的一个很好的例子是走链接列表的枚举.你没有修改列表头,你只需要一个指向开始节点的指针.
后者的一个很好的例子是当你将节点推入堆栈时,列表头指针本身将在完成函数之前被更改.
像C中的所有东西(数组都不能承受)如果你想修改某些东西作为输出参数,你需要将参数声明为正式指针类型并传递你正在修改的东西的地址.在后一种情况下(我认为是引起混淆的情况),我们需要修改的是一个指针变量本身,因此它必须被声明为指针指针,然后传入指针的地址.
例子大声说话,所以看看:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
void traverse(struct node* p)
{
while (p)
{
printf("%d\n", p->data);
p = p->next; // note. modifies only our local variable p.
// caller side uneffected.
}
}
void insert(struct node **pp, int data)
{
struct node *p = malloc(sizeof(*p));
p->data = data;
p->next = *pp;
*pp = p; // note: save new list head here.
}
int main(int argc, char *argv[])
{
struct node *head = NULL;
insert(&head, 1);
printf("head = %p\n", head);
insert(&head, 2);
printf("head = %p\n", head);
insert(&head, 3);
printf("head = %p\n", head);
traverse(head);
// yes, I know its leaking memory. that isn't the subject of this question.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产量
head = 0x1001000e0
head = 0x100103b40
head = 0x100103b50
3
2
1
Run Code Online (Sandbox Code Playgroud)