C语言使用引用传递反而报错,如何解决?

C语言使用引用传递反而报错

以下是我第一遍写的,成功运行的文件

/**
 * 说明:王道版数据结构,LNode *, LinkList两个东西虽然实际表示的东西是一样的,
 * 但是LNode *强调这是一个结点的指针,LinkList则表示一个链表(头指针、头结点的指针)
 * 其次,王道版链表是带头结点的
 */
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"

typedef struct LNode { // 定义单链表结点类型
    int data; // 每个结点存放一个数据元素
    struct LNode *next; // 指针指向下一个结点
} LNode, *LinkList;


// 初始化一个单链表(带头结点)
LinkList initList(LinkList L) {
    L = (LNode *) malloc(sizeof(LNode)); // 分配一个头结点
    L->data = 999;//头结点的数据域可以没有,也可以是别的,比如可以是链表长度
    if (L == NULL) { // 内存不足,分配失败
        printf("L == NULL");
        return 0;
    }
    L->next = NULL; // 头结点之后暂时还没有结点

    return L;
}

/**
 * 在第i个位置插入元素e(带头结点)
 */
bool ListInsert(LinkList L, int i, int e) {
    if (i < 1) {
        printf("i < 1");
        return 0;
    }


    LNode *p; // 创建一个当前指向的结点
    p = L; // 初始化指向到头结点

    int j = 1;
    //将p指向某结点,该结点后面要插入新结点
    while (j < i) {
        p = p->next;
        j++;
    }

    LNode *s; // 新建一个待插入的新节点
    s = (LNode *) malloc(sizeof(LNode)); // 给新节点分配内存
    s->data = e; // 给新节点放入数据
    s->next = p->next; // 新节点指向当前结点的下一个结点
    p->next = s;  // 原结点指针改为指向到新创建的结点

}

void readAll(LinkList L) {
    LNode *p;
    p = L;
    while (p->next != NULL) {
        p = p->next;
        printf("%d \n", p->data);
    }
}

void deleteItem(LinkList L, int i) {
    int j;
    LNode *s;
    s = L;
    for (j = 0; j < i - 1; j++) {
        s = s->next;
    }
    LNode *t = s->next;
    s->next = s->next->next;
    free(t);
}

int main() {
    LinkList L;
//    LNode L;
    L = initList(L);
    ListInsert(L, 1, 111);
    ListInsert(L, 1, 222);
    ListInsert(L, 1, 333);
    printf("三次插入后的结果\n");
    readAll(L);
    printf("删除后的结果\n");
    deleteItem(L, 2);
    readAll(L);

    return 0;
}


注意到王道书上有一个细节,在需要更改链表本身的时候,在参数列表里会增加一个取地址符,但是我加上之后编译器反而报错了

img

还是不明白这里为什么要加取地址符,我们本身传递进去的就是一个指针变量(LinkList),输入指针变量已经是引用传递了吧?

c++才有引用传递,c语言里没有

C++引用,供参考:https://baike.baidu.com/item/C%2B%2B%E5%BC%95%E7%94%A8/463646?fr=aladdin

img

题主的代码里,将源文件.c 的后缀,重新保存成 .cpp后缀,即可实现,初始化单链表函数可以不需返回值,修改如下,供参考 :

#include "stdio.h"
#include "stdlib.h"
//#include "stdbool.h"

typedef struct LNode { // 定义单链表结点类型
    int data; // 每个结点存放一个数据元素
    struct LNode *next; // 指针指向下一个结点
} LNode, *LinkList;


// 初始化一个单链表(带头结点)
void initList(LinkList& L) {    //修改  LinkList initList(LinkList& L)
    L = (LNode *) malloc(sizeof(LNode)); // 分配一个头结点
    L->data = 999;//头结点的数据域可以没有,也可以是别的,比如可以是链表长度
    if (L == NULL) { // 内存不足,分配失败
        printf("L == NULL");
        return;  //return 0;   //修改
    }
    L->next = NULL; // 头结点之后暂时还没有结点

    //return L;               //修改
}

/**
 * 在第i个位置插入元素e(带头结点)
 */
bool ListInsert(LinkList L, int i, int e) {
    if (i < 1) {
        printf("i < 1");
        return 0;
    }


    LNode *p; // 创建一个当前指向的结点
    p = L; // 初始化指向到头结点

    int j = 1;
    //将p指向某结点,该结点后面要插入新结点
    while (j < i) {
        p = p->next;
        j++;
    }

    LNode *s; // 新建一个待插入的新节点
    s = (LNode *) malloc(sizeof(LNode)); // 给新节点分配内存
    s->data = e; // 给新节点放入数据
    s->next = p->next; // 新节点指向当前结点的下一个结点
    p->next = s;  // 原结点指针改为指向到新创建的结点

}

void readAll(LinkList L) {
    LNode *p;
    p = L;
    while (p->next != NULL) {
        p = p->next;
        printf("%d \n", p->data);
    }
}

void deleteItem(LinkList L, int i) {
    int j;
    LNode *s;
    s = L;
    for (j = 0; j < i - 1; j++) {
        s = s->next;
    }
    LNode *t = s->next;
    s->next = s->next->next;
    free(t);
}

int main() {
    LinkList L;
    //LNode L;
    //L =        //修改
    initList(L); //修改
    ListInsert(L, 1, 111);
    ListInsert(L, 1, 222);
    ListInsert(L, 1, 333);
    printf("三次插入后的结果\n");
    readAll(L);
    printf("删除后的结果\n");
    deleteItem(L, 2);
    readAll(L);

    return 0;
}

王道书上是伪代码,建议买上机的书边敲边练,另外一般现在上机是用的c++,引用在中是没有的,指针和引用不能混为一谈,可以搜索指针和引用的区别,例如引用不会导致断链而指针可能导致,这涉及底层的内存调用。