对C指针和内存地址有一些疑问

Having some doubts about C pointers and memory address

我真的是 C 的新手,我有一段关于 C 中 LinkedList 的代码:

struct ListNode* addnode(struct ListNode *head,int val)
{
    struct ListNode* newnode = malloc(sizeof(struct ListNode));
    newnode->val = val;
    newnode->next = NULL;
    if (!head) head = newnode;
    else {
        struct ListNode *this = head;
        while(this->next)
            this = this->next;
        this->next = newnode;
    }
    return head;
}

int main(void)
{
    struct ListNode *head = NULL;

    head = addnode(head,4);
    addnode(head,9);
    addnode(head,1);

    return 0;
}

我的问题是:主要是为什么我要写

    addnode(head,4);
    addnode(head,9);
    addnode(head,1);

而不是

head = addnode(head,4);
    addnode(head,9);
    addnode(head,1);

不起作用?第一个是创建以下链表:4->9->1,第二个是创建 3 个不同的链表头。但这不就和我们一直使用 head 的内存地址一样吗?所以head总是在保存他之前的节点。

提前致谢,非常感谢您的回答

最初指针head被初始化为空指针

struct ListNode *head = NULL;

此指针按值传递给函数addnode

addnode(head,4);

该函数处理在 main 中声明的指针 head 值的副本,用作函数的参数表达式。更改副本不会影响原始指针 head.

所以在调用之后指针 head 仍然是一个空指针。

函数returns指针副本的修改值

struct ListNode* addnode(struct ListNode *head,int val)
{
    //... 
    if (!head) head = newnode;
    //...
    return head;
}

要改变原来的指针head你需要将返回值赋值给指针head like

head = addnode(head,4);

现在指针head指向列表的第一个节点。

该函数的所有其他调用

addnode(head,9);
addnode(head,1);

将新节点追加到列表的尾部。也就是说,这些调用不会影响指向列表第一个节点的指针的值。所以没有必要将函数的返回值分配给指针 head 尽管你可以写

head = addnode(head,9);
head = addnode(head,1);

为了更清楚地考虑一个非常简单的例子

#include <stdio.h>

int f( int x )
{
    x += 1;

    return x;
}

int main( void )
{
    x = 0;

    f( x );

    printf( "x = %d\n", x );
}

如果您不会替换此声明

    f( x );

    x = f( x );

那么调用函数f后变量x不会在main中改变,因为函数f改变了变量x值的副本用作函数参数。