简体   繁体   English

删除带有指向 C 中的指针的列表

[英]Deleting a list with pointer to pointer in C

The partial code, in C, is here: C 中的部分代码在这里:

typedef struct List {
  double v;
  struct List *next;
} List;

void deleteList (List **p) {
  *p = (*p)->next;
}

I am confused about how the deleteList function is working.我对 deleteList function 的工作方式感到困惑。 So the arguement is a pointer to a pointer to a List structure.所以争论是一个指向 List 结构的指针。 So we have:所以我们有:

p : pointer_2 --> pointer_1 --> List

So I have some questions:所以我有一些问题:

  1. So what is *p in the function deleteList()?那么 function deleteList() 中的 *p 是什么? Is it pointer_1 or something else?pointer_1还是别的什么?
  2. Does *p before = mean the same as *p after the = sign? = 之前的 *p 与 = 符号之后的 *p 的含义相同吗?
  3. Is there a difference between *p and (*p)? *p 和 (*p) 之间有区别吗?

Say we have:假设我们有:

... la --> lb --> lc --> ld ....

And say we want to delete lb. I get the idea, theoretically.说我们要删除磅。理论上我明白了。 You alter the la->next to point to lc.您将 la->next 更改为指向 lc。 But I am confused about the pointer business.但我对指针业务感到困惑。 What is the argument to deleteList()? deleteList() 的参数是什么? Is it, deleteList(la->next)?是,deleteList(la->next)? Or something else?或者是其他东西? And then the really confusing part.然后是真正令人困惑的部分。 *p =... is supposed to be la->next because this is the pointer we want to alter. *p =... 应该是 la->next 因为这是我们要更改的指针。 But then...(*p)->next, wouldn't this just be the lb?但是然后...(*p)->next,这不就是磅吗? But we want lc?但是我们想要lc? So it seems like *p have different meaning in the same line?!所以看起来 *p 在同一行中有不同的含义?!

Let;s at first write the function correctly.让我们首先正确地编写 function。

void deleteList( List **head ) 
{
    while ( *head != NULL )
    {
        List *tmp = *head;
        *head = ( *head )->next;
        free( tmp ); 
    }
}

A pointer to the head node is passed to the function by reference.指向头节点的指针通过引用传递给 function。

If you will define the function like如果您要定义 function 之类的

void deleteList( List *head ) 
{
    while ( head != NULL )
    {
        List *tmp = head;
        head = head->next;
        free( tmp ); 
    }
}

that is if the pointer will not be passed by reference then the function will deal with a copy of the pointer.也就是说,如果指针不会通过引用传递,那么 function 将处理指针的副本。 Changing a copy does not influence on the original pointer.更改副本不会影响原始指针。

Consider the following demonstrative program.考虑以下演示程序。

#include <stdio.h>
#include <stdlib.h>

void f( int *p )
{
    p = NULL;
}

int main(void) 
{
    int x = 10;
    int *px = &x;

    printf( "Before the function call px = %p\n", ( void * )px );   

    f( px );

    printf( "Adter  the function call px = %p\n", ( void * )px );   

    return 0;
}

Its output might look like它的 output 可能看起来像

Before the function call px = 0x7ffe26689a2c
Adter  the function call px = 0x7ffe26689a2c

That is the original pointer px was not changed because the function dealt with a copy of the pointer.那就是原始指针px没有改变,因为 function 处理了指针的副本。

To change the pointer you need to pass it to the function by reference要更改指针,您需要通过引用将其传递给 function

#include <stdio.h>
#include <stdlib.h>

void f( int **p )
{
    *p = NULL;
}

int main(void) 
{
    int x = 10;
    int *px = &x;

    printf( "Before the function call px = %p\n", ( void * )px );   

    f( &px );

    printf( "Adter  the function call px = %p\n", ( void * )px );   

    return 0;
}

Now the program output might look like现在程序 output 可能看起来像

Before the function call px = 0x7ffed60815fc
Adter  the function call px = (nil)

Within the function you need to dereference the parameter to get the access to the passed by reference pointer.在 function 中,您需要取消引用参数才能访问通过引用传递的指针。

*p = NULL;

^^^^ ^^^^

The same occurs in the function deleteNode . function deleteNode中也会发生同样的情况。 To check whether the passed pointer is equal to NULL there is used the following statement要检查传递的指针是否等于 NULL 使用以下语句

while ( *head != NULL )
       ^^^

To access the data member next of the node pointed to by the origibal pointer you again have to dereference the parameter to get access to the original pointer要访问原始指针指向的节点的next数据成员,您必须再次取消引用参数才能访问原始指针

*head

So this expression yields the original pointer.所以这个表达式产生了原始指针。 So to access the data member next you have to write所以接下来要访问数据成员,你必须写

( *head )->next

You are using the parentheses because the postfix operator -> has a higher priority but you need at first to get the original pointer.您正在使用括号,因为后缀运算符 -> 具有更高的优先级,但您首先需要获取原始指针。

That is if you had no a referenced pointer you would write也就是说,如果你没有引用的指针,你会写

head->next

But when you have a referenced pointer that is when you have a pointer to an original pointer then to get the original pointer you have to derefernce the referenceing pointer like但是,当您有一个引用指针时,即当您有一个指向原始指针的指针时,要获取原始指针,您必须取消引用引用指针,例如

( *head )->next

You could write the function without accepting the pointer to the head node by reference.您可以编写 function 而不通过引用接受指向头节点的指针。 But in this case you should to add in the caller one more statement that will set the pointer head to NULL.但在这种情况下,您应该在调用者中再添加一条语句,将指针头设置为 NULL。

For example例如

void deleteList( List *head ) 
{
    while ( head != NULL )
    {
        List *tmp = head;
        head = head->next;
        free( tmp ); 
    }
}

and in the caller you need to write在调用者中你需要写

List *head - NULL;

// the code thatf fills the list

deleteList( head );
head = NULL;

Or the function could return a null pointer like或者 function 可以返回 null 指针,如

List * deleteList( List *head ) 
{
    while ( head != NULL )
    {
        List *tmp = head;
        head = head->next;
        free( tmp ); 
    }

    return head;
}

and in the caller you could write在调用者中你可以写

List *head - NULL;

// the code thatf fills the list

head = deleteList( head );

The advantage of defining the function that accepts the pointer to the head node by reference is that the user of the function does not need to remember to set the pointer to NULL by himself.定义function通过引用接受指向头节点的指针的好处是function的用户不需要记住自己设置指向Z6C3E226B4D4795D518AB341B0824EC2的指针。

in deleteList function: before you pass to the next element you must free the element you point to.deleteList function 中:在传递到下一个元素之前,您必须释放您指向的元素。

void deleteList (List **p) {
  while(*p != NULL){
    List *nextNode = (*p)->next;
    free(*P);
    *p= nextNode;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM