结构指针的单指针或双指针

Single or Double Pointer for Struct pointers

提问人:Surya Majumder 提问时间:2/28/2022 最后编辑:Vlad from MoscowSurya Majumder 更新时间:2/28/2022 访问量:328

问:

我试图编写一些代码来检查调用函数时结构指针的指针函数。

我尝试对树或链表使用单指针,但发现通常如果我编写一个 void 函数并且 head 或 root 不是全局的,它会给我带来分割错误。

我找到的唯一解决方案是返回 head(或 root) 的值,或者如果我不想返回任何内容(但需要调用 &),则使用双指针。

我的代码是:

//This one gives Segmentation Error always.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

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

typedef struct node node;

void addnode(node *head, node *tail, int d)
{
    node *newnode = (node *)malloc(sizeof(node));
    newnode->data = d;
    newnode->next = NULL;
    if(head==NULL)
    {
        head = tail = newnode;
    }
    else
    {
        tail->next = newnode;
        tail = newnode;
    }
}


//This one also works [but sometimes gives Segmentation Error (No Idea why)]. But it has a return
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

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

typedef struct node node;

void addnode(node *head, node *tail, int d)
{
    node *newnode = (node *)malloc(sizeof(node));
    newnode->data = d;
    newnode->next = NULL;
    if(head==NULL)
    {
        head = tail = newnode;
    }
    else
    {
        tail->next = newnode;
        tail = newnode;
    }
    return head;
}


//This one also works fine but here I don't need to return anything.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

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

typedef struct node node;

void addnode(node **head, node **tail, int d)   // Here head and tail is called with & eg: addnode(&head1,&tail1,data);
{
    node *newnode = (node *)malloc(sizeof(node));
    newnode->data = d;
    newnode->next = NULL;
    if(head==NULL)
    {
        *head = *tail = newnode;
    }
    else
    {
        (*tail)->next = newnode;
        *tail = newnode;
    }  //No return
}

我的问题是为什么会发生这个错误?难道我们不需要在需要时使用指针,甚至使用变量 从一个只能有一个返回语句的函数中具有多个值?

除了关于单指针和双指针之外,我们是否也使用数组指针进行第一种情况,甚至在数组(或任何其他指针类型)中,当我们执行 *arr1 = *arr2 时; 那么修改 arr1 不会修改 arr2(因为现在它们指向相同的数据)?如果是这样的话,为什么我需要在这里使用双指针来修改和访问它们?

我真的很困惑。

请帮忙。

C 指针 结构 Pass-By-Reference Pass-By-Value

评论

0赞 जलजनक 2/28/2022
阅读更多关于“按参考调用”和“按值调用”的信息。在您的情况下,“引用调用”有效;这是一个双指针,因为变量已经是一个指针。
0赞 Ptit Xav 2/28/2022
指针是一个变量,包含指向内存中某个位置的地址。因此,如果传递指针包含的地址,则无法修改此值 baca use,您不知道保存此地址的指针在内存中的位置。为了能够修改它,你需要有它的地址,即指针的地址(例如:&head),它是指向指针=双指针的指针。

答:

2赞 Vlad from Moscow 2/28/2022 #1

此功能

void addnode(node *head, node *tail, int d)

处理原始指针值的副本并用作参数表达式。更改副本不会影响原始指针。headtail

此功能

void addnode(node *head, node *tail, int d)
{
    //...
    return head;
}

具有返回类型。因此,编译器应发出错误消息,因为如果函数的返回类型为 ,则返回语句不应返回值。voidvoid

但是,如果您将按以下方式声明该函数

node * addnode(node *head, node *tail, int d)
{
    //...
    return head;
}

然而,它会遇到与第一个函数相对于指针相同的问题,因为该函数将再次处理原始指针的副本,并且指针的新值不会返回给调用方。tailtail

此函数的定义

void addnode(node **head, node **tail, int d)   // Here head and tail is called with & eg: addnode(&head1,&tail1,data);
{
    node *newnode = (node *)malloc(sizeof(node));
    newnode->data = d;
    newnode->next = NULL;
    if(head==NULL)
    {
        *head = *tail = newnode;
    }
    else
    {
        (*tail)->next = newnode;
        *tail = newnode;
    }  //No return
}

有一个错误。而不是这个 if 语句

    if(head==NULL)

你必须写

    if ( *head == NULL )

该函数之所以工作,是因为指针 和 通过指向它们的指针通过引用传递给函数。因此,取消引用指针,例如在此语句中headtail

        *head = *tail = newnode;

您可以直接访问原始指针(而不是处理原始指针值的副本)并可以更改它们。

但无论如何,你的方法并不好。

您应该声明另一个将包含指针的结构,例如headtail

typedef struct list
{
    node *head;
    node *tail;
} list;

然后在 main 中,您可以声明一个结构类型的对象,例如

list list1 = { .head =  NULL, .tail = NULL };

在本例中,函数将如下所示addnode

int addnode( list *lst, int data )
{
    node *newnode = malloc( sizeof( node ) );
    int success = newnode != NULL;

    if ( success )
    {
        newnode->data = data;
        newnode->next = NULL;

        if ( lst->head == NULL )
        {
            lst->head = newnode;
        }
        else
        {
            lst->tail->next = newnode;
        }

        lst->tail = newnode;
    }

    return success;
}

并且该函数可以像例如一样调用

addnode( &list1, data );

if ( !addnode( &list1, data ) )
{
    puts( "Error. Not enough memory" );
}

评论

0赞 Surya Majumder 2/28/2022
谢谢。它真的消除了我的很多疑虑。但是我有两个问题:首先,在第三种情况下,忽略了尾部,为什么我仍然需要一个双指针作为头部?如果我使用单个指针,那么正如您所说,这些是副本,那么为什么数组指针不会发生这种情况呢?如果您能澄清这一点,我将不胜感激。提前致谢。
0赞 Vlad from Moscow 2/28/2022
@SuryaMajumder 我不明白你的第一个问题。一切都在我的回答中解释。至于第二个问题,那么当你将数组传递给函数时,它会隐式转换为指向其第一个元素的指针。因此,使用指针和指针算术,您可以更改数组的任何元素。事实上,数组的元素是通过指向它们的指针通过引用传递的。这是一个像这样的调用 function( array );与写 function( &array[0] );
0赞 Surya Majumder 2/28/2022
非常感谢来自莫斯科@Vlad。谢谢。