Pointers 为什么我的函数使用按值调用方法?

Pointers 为什么我的函数使用按值调用方法?,pointers,Pointers,我不知道为什么在最后一行它打印的是第一个元素的数据而不是最后一个元素的数据。我需要解释 // A simple C program for traversal of a linked list #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; }; // This function prints contents of lin

我不知道为什么在最后一行它打印的是第一个元素的数据而不是最后一个元素的数据。我需要解释

// A simple C program for traversal of a linked list 
#include <stdio.h> 
#include <stdlib.h> 

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

// This function prints contents of linked list starting from 
// the given node 
void printList(struct Node* n) 
{ 
    while (n != NULL) { 
        printf(" %d ", n->data); 
        n = n->next; 
    } 
} 

int main() 
{ 
    struct Node* head = NULL; 
    struct Node* second = NULL; 
    struct Node* third = NULL; 

    // allocate 3 nodes in the heap 
    head = (struct Node*)malloc(sizeof(struct Node)); 
    second = (struct Node*)malloc(sizeof(struct Node)); 
    third = (struct Node*)malloc(sizeof(struct Node)); 

    head->data = 1; // assign data in first node 
    head->next = second; // Link first node with second 

    second->data = 2; // assign data to second node 
    second->next = third; 

    third->data = 3; // assign data to third node 
    third->next = NULL; 

    printList(head); 
    
    printf("%d",head->data);

    return 0; 
}

//用于遍历链表的简单C程序
#包括
#包括
结构节点{
int数据;
结构节点*下一步;
}; 
//此函数从开始打印链表的内容
//给定节点
无效打印列表(结构节点*n)
{ 
而(n!=NULL){
printf(“%d”,n->data);
n=n->next;
} 
} 
int main()
{ 
结构节点*head=NULL;
结构节点*second=NULL;
结构节点*third=NULL;
//在堆中分配3个节点
head=(结构节点*)malloc(sizeof(结构节点));
第二个=(结构节点*)malloc(sizeof(结构节点));
第三个=(结构节点*)malloc(sizeof(结构节点));
head->data=1;//在第一个节点中分配数据
head->next=second;//将第一个节点链接到第二个节点
第二个->数据=2;//将数据分配给第二个节点
第二->下一个=第三个;
第三->数据=3;//将数据分配给第三个节点
第三->下一步=空;
印刷品清单(标题);
printf(“%d”,头部->数据);
返回0;
}
因为函数正在接受指针,所以应该通过引用调用它。 在函数的最后一个循环中,当n指针等于NULL时。 但在这段代码的最后一行是打印我的链表的第一个列表的数据。

在C中没有按引用传递,所有内容都是按值传递的。人们使用指针来模拟按引用传递,这是因为您可以使用传入指针来获取相同的底层数据项

换句话说,即使传入的指针是函数中的按值传递副本,但它与原始指针具有相同的值这一事实意味着它们都指向相同的对象

但是,如果要更改的对象已经是指针,则需要指向指针的指针来执行此模拟

我可以给你密码,但是,相信我,这不是你想要的。这意味着列表打印代码将破坏列表本身,因为头部现在将指向NULL

下面是一些代码,它演示了如何执行类似的操作,使用此双指针方法在函数外部更改指针:

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

void allocateSomeMem(void **pPtr, size_t sz) {
    *pPtr = malloc(sz);
}

int main(void) {
    void *x = NULL;
    printf("%p\n", x);
    allocateSomeMem(&x, 42);
    printf("%p\n", x);
}

现在,很明显,对于所示的简单示例,您不会这样做,只需返回新指针并将其指定给
x
,就会容易得多。但这只是说明要使用的方法。

实际上,您所做的并不是在实际的链表中进行的,它不是通过引用传递的

void printList(struct Node* n) 
{ 
   /* some code here */
} 

void main()
{
    /* all your code here */
    printList(head);
}    
因此,如果要更改实际链表中的头,必须将指针头的地址传递给函数 像这样的

int append_list(node **head, int data)
{
    while((*head)->next!=NULL)
    {
        (*head) = (*head)->next;
    }
}



int main()
{
    struct node *head = NULL;
 
    /* add nodes */

    print_list(&head);

}
下面是对代码的修改:

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

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

   // This function prints contents of linked list starting from 
   // the given node 
   void printList(struct Node** n) 
   { 
        while ((*n)->next != NULL) { 
        printf(" %d ", (*n)->data); 
        (*n) = (*n)->next; 
   } 
} 

int main() 
{ 
   struct Node* head = NULL; 
   struct Node* second = NULL; 
   struct Node* third = NULL; 

   // allocate 3 nodes in the heap 
   head = (struct Node*)malloc(sizeof(struct Node)); 
   second = (struct Node*)malloc(sizeof(struct Node)); 
   third = (struct Node*)malloc(sizeof(struct Node)); 

   head->data = 1; // assign data in first node 
   head->next = second; // Link first node with second 

   second->data = 2; // assign data to second node 
   second->next = third; 

   third->data = 3; // assign data to third node 
   third->next = NULL; 

   printList(&head); 

   printf("%d",head->data);

   return 0; 
}
由于您已使用(*head)进行遍历,因此您不再具有访问列表的权限,因此如果您尝试访问,将出现分段错误

 (*head)->next
但我不建议这样做,因为现在您将无法释放内存

  1 2 3
 (*head)->next