根据我目前对C工作原理的了解,如果我以这种方式使用函数List_int_add(linklist, 50),而不必分配linklist = List_int_add(linklist, 50),那么linklist的值将更新为返回值List_int_add(linklist, 50),因为代替linklist的是参数Node_int * head,而函数返回head。既然参数是指针,那么List_int_add(linklist, 50)是否足以更新linklist
当使用List_int_add(linklist, 50)时,List_int_print(linklist)的输出将从100开始,而不是50。但如果我分配到linklist=List_int_add(linklist, 50),它就可以正常工作。
(请忽略返回时的类型转换,这是由于我以前是如何编写代码的,我正在编辑代码,我知道这是不必要的)
提前谢谢。
在main.c中:

#include <stdio.h>
#include <stdlib.h>
#include "LinkedList/linkedlist.h"
int main(int argc, char ** argv){
    Node_int * linklist = NULL;
    linklist = List_int_add(linklist, 50);
    linklist = List_int_add(linklist, 100);
    linklist = List_int_add(linklist, 150);
    linklist = List_int_add(linklist, 200);
    linklist = List_int_add(linklist, 250);
    linklist = List_int_add(linklist, 300);
    linklist = List_int_add(linklist, 350);

    linklist = List_int_remove(linklist,50);
    List_int_print(linklist);
    List_int_destroy(linklist);
    if (linklist == NULL)
        List_int_print(linklist);
    return EXIT_SUCCESS;
}

在linkedlist.c中:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "linkedlist.h"

/* Node_int_construct: create a Node_int */
static Node_int * Node_int_construct(int val);

/* Node_int_construct: create a Node_int   */
static Node_int * Node_int_construct(int val){
    Node_int * nd = (Node_int *) malloc(sizeof(Node_int));
    nd->next = NULL;
    nd->prev = NULL;
    nd->value = val;
    return nd;
}

Node_int * List_int_add(Node_int * head, int val){
    Node_int * nd = Node_int_construct(val);
    // insert at the end
    Node_int * ptr = (Node_int *) head;
    if (ptr == NULL){
        head = nd;
        head -> next = NULL;
        head -> prev = NULL;
        return (Node_int *) head;
    }
    while (ptr->next != NULL){
        ptr = ptr->next;
    }
    nd->prev = ptr;
    ptr->next = nd;
    return (Node_int *) head;
}

Node_int * List_int_remove(Node_int * head, int val){
    Node_int * target = List_int_search((const Node_int * const) head, val);
    if (target == NULL){
        return target;
    }
    if (target == head){
        head = head->next;
        head->prev = NULL;
        free(target);
    }
    else if (target->next == NULL){
        Node_int * ptr = target->prev;
        ptr->next = NULL;
        free(target);
    }
    else {
        Node_int * prev = target->prev;
        Node_int * next = target->next;
        prev->next = next;
        next->prev = prev;
        free(target);
    }
    return head;
}

void List_int_destroy(Node_int * head){
    Node_int * ptr = head;
    Node_int * temp;
    while (ptr != NULL){
        temp = ptr;
        ptr = ptr->next;
        free(temp);
        }
}


Node_int * List_int_search(const Node_int * const head, int val){
    Node_int * ptr = (Node_int *) head;
    while (ptr != NULL){
        if (ptr->value == val){
            return ptr;
        }
        ptr = ptr->next;
    }
    return ptr;
}

void List_int_print(const Node_int * const head){
    Node_int * ptr = (Node_int*) head;
    while (ptr != NULL){
        printf("> %d \n", ptr->value);
        ptr = ptr->next;
    }
}

在linkedlist.h中:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H

typedef struct _node_int {
    struct _node_int * next;
    struct _node_int * prev;
    int value;
} Node_int;

/* List_int_add: add Node_int at the end of list. */
Node_int * List_int_add(Node_int * head, int val);

/* List_int_remove: remove first item that matches val.
    Returns head if successful, returns NULL if failure */
Node_int * List_int_remove(Node_int * head, int val);

/* List_int_destroy: Delete entire list. */
void List_int_destroy(Node_int * head);

/* List_int_search: Returns pointer to node of the first matching item in list,
    NULL if node is not found. */
Node_int * List_int_search(const Node_int * const head, int val);

/* List_int_print: print int list. */
void List_int_print(const Node_int * const head);
#endif

最佳答案

为了确保没有误解,我将陈述一些我认为你已经知道的事情,但这只是为了清楚的答案。
C中的所有内容都是按值传递的。这意味着,无论何时将参数赋给函数,实际给出的都是该参数的副本(具有参数值的自动变量)。
为了能够在不影响返回值的情况下使用函数修改变量的值(例如,x),我们将传递x的引用。这样,函数将接收到地址x的副本,从而可以通过取消引用直接修改x=modify_x_please(x)
例如:

void increment_int(int *x){
   (*x)++;
}

以这种方式使用:
int x=3;
increment_int(&x);
/*here x is equal to 4*/

以上这些你都已经知道了,但让我们想象最后一个例子:
void set_pointer_to_null(void **p){
(*p)=NULL;
}

用法:
int * p;
p=&x;
set_pointer_to_null(&p);
/*p is NULL here*/

在这里,它与你的问题越来越相关:如果你想修改一个指针,你需要传递一个指针的引用。
这意味着将函数签名更改为x,并使用x而不是Node_int * List_int_add(Node_int ** head, int val)等。。。
你甚至可以有一个(*head),所以这个想法变得更加清晰。你可以这样想:如果我想修改一个列表,我会传递这个列表的地址。列表只是一个节点的地址,这完全是另一回事。但我知道也有人反对“过度使用”typedef,所以如果你感兴趣的话,我建议你考虑一下使用typedef的缺点。
最后一件事,如果add和remove函数获得了好的引用并对它们进行了很好的修改,那么您甚至可能不需要返回。你可以让他们的返回类型无效。

08-26 19:21