简体   繁体   English

在函数中传递双指针

[英]Passing a double pointer in a function

I was creating a program with linked lists in C. I created a head variable in main function.我在 C 中创建了一个带有链表的程序。我在main函数中创建了一个head变量。 Then I passed it by reference to a function insert_at_head(struct node **head) .然后我通过引用函数insert_at_head(struct node **head)传递它。

I have another function for inserting at tail.我有另一个插入尾部的功能。 In a base condition, if my list is empty, I want to call insert_at_head(struct node **head) again.在基本条件下,如果我的列表为空,我想再次调用insert_at_head(struct node **head) But I am getting confused in passing the actual parameter.但是我在传递实际参数时感到困惑。 Should it be insert_at_head (&(*head)) or insert_at_head (head) ?应该是insert_at_head (&(*head))还是insert_at_head (head)

Personally, I think both are same, because both of them are passing a double pointer.就个人而言,我认为两者是相同的,因为它们都传递了一个双指针。 Which one should I use?我应该使用哪一种?

Regarding the insert_at_head function, you have to remember that in C all arguments are passed by value .关于insert_at_head函数,您必须记住,在 C 中所有参数都是按值传递 That means the value is copied into the argument variable.这意味着该值被复制到参数变量中。 Inside the function, if you modify the argument variable (like assigning to it) then you only modify the copy, not the original.在函数内部,如果你修改了参数变量(比如给它赋值),那么你只能修改副本,而不是原始变量。

If you want to modify the original value, then you have to emulate pass by reference , which can be done by using the address-of operator & to pass a pointer to the value.如果要修改原始值,则必须模拟通过引用传递,这可以通过使用地址运算符&传递指向该值的指针来完成。 If you want to do this for a variable which is a pointer, then you get a pointer to a pointer.如果您想对作为指针的变量执行此操作,那么您将获得一个指向指针的指针。

Here's a simple example:这是一个简单的例子:

#include <stdio.h>

// Define two global variables
int a = 10;
int b = 20;

void change1(int *x)
{
    x = &b;  // Make x point to b
}

void change2(int **x)
{
    *x = &b;  // Make *x point to b
}

int main(void)
{
    // Define a pointer variable, and make it point to the global variable a
    int *pointer_to_a = &a;

    // Will print the value of a, i.e. 10
    printf("*pointer_to_a = %d\n", *pointer_to_a);

    // Try to change where pointer_to_a is pointing
    change1(pointer_to_a);

    // Here pointer_to_a is *still* pointing to a, it wasn't changed, will print the value 10
    printf("*pointer_to_a = %d\n", *pointer_to_a);

    // Do another attempt to change where pointer_to_a is pointing
    change2(&pointer_to_a);

    // Now pointer_to_a is no longer pointing to a, it points to b and 20 will be printed
    printf("*pointer_to_a = %d\n", *pointer_to_a);
}

Getting back to the insert_at_head function (whose functionality we can only speculate about) I'm guessing it will add to the head of a linked list.回到insert_at_head函数(我们只能推测其功能)我猜它会添加到链表的头部。 It will do that by modifying where the head of the list is pointing.它将通过修改列表头部指向的位置来做到这一点。

As seen by the example above, unless we pass a pointer to the pointer, assignments to the head will be lost once the function ends.从上面的例子可以看出,除非我们传递一个指向该指针的指针,否则一旦函数结束,对 head 的赋值就会丢失。 And this is solved by using pointer to a pointer, and passing the head pointer using the address-of operator & when calling the function.这是通过使用指向指针的指针并在调用函数时使用地址运算符&传递头指针来解决的。

Assuming the type of head is struct node ** , then you can pass it directly to a function expecting a parameter of that type.假设head的类型是struct node ** ,那么您可以将它直接传递给需要该类型参数的函数。

&(*head) is exactly the same as head . &(*head)是完全一样的head When the operand of the & operator is the result of the unary * operator, they cancel each other out and neither is actually evaluated.&运算符的操作数是一元*运算符的结果时,它们会相互抵消,并且实际上都不会计算。

This is spelled out in section 6.5.3.2p3 of the C standard regarding the address-of and indirection operators:这在 C 标准的第 6.5.3.2p3 节中关于地址和间接运算符的说明中有详细说明:

The unary & operator yields the address of its operand.一元&运算符产生其操作数的地址。 If the operand has type ''type'', the result has type ''pointer to type''.如果操作数的类型为“type”,则结果的类型为“指向类型的指针”。 If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.如果操作数是一元*运算符的结果,则该运算符和&运算符都不会被计算,结果就像两者都被省略了一样,除了对运算符的约束仍然适用并且结果不是左值。

So if head is a pointer, the expressions head and &(*head) are equivalent.所以如果head是一个指针,表达式head&(*head)是等价的。

In C language, you can't pass a variable by reference.在C语言中,你无法通过引用传递的变量。

You can, however, pass a pointer to your variable.但是,您可以将指针传递给您的变量。 Of course the pointer is passed by value.当然,指针是按值传递的。 For example, if you declare a varable head which is a pointer to a structure node :例如,如果您声明一个变量head ,它是指向结构node的指针:

struct node* head;

you can prepare a function to operate on such variable:你可以准备一个函数来操作这样的变量:

void insert_at_head(struct node** ptr);

Then you call it with:然后你调用它:

insert_at_head(&head);

where operator & yield a pointer to your variable, ie a value of the struct node ** type.其中 operator &产生一个指向您的变量的指针,即struct node **类型的值。 That value is passed to the callee.被传递给被调用者。

Of course, another function, say:当然,另一个功能,说:

void append_at_end(struct node** ptr);

can call the former function when necessary, passing it the same pointer it got as a parameter:可以在必要时调用前一个函数,将它作为参数获得的指针传递给它:

void append_at_end(struct node** ptr)
{
    if(*ptr == NULL)          /* list is empty */
        insert_at_head(ptr);  /* the same pointer to a head pointer */
    else {
        /* other stuff */
    }
}

Should it be insert_at_head (&(*head)) or insert_at_head (head)?应该是 insert_at_head (&(*head)) 还是 insert_at_head (head)?

None of them.他们都没有。 They are both wrong and also the same.他们都是错误的,也是一样的。

If you did the following in your main:如果您在主程序中执行了以下操作:

struct node head;

You will start having problems in your code.您将开始在代码中遇到问题。

You can make it work but it is the wrong way.你可以让它工作,但这是错误的方式。

To make it work you must do the following in your main:要使其工作,您必须在主要内容中执行以下操作:

struct node head;
struct node *phead=&head;

insert_at_head(&phead).

The right way to go is:正确的做法是:

struct node *head=NULL;

insert_at_head(&head).

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

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