首页 新闻 会员 周边

关于参数传递的疑惑

0
悬赏园豆:100 [已解决问题] 解决于 2022-09-05 11:27
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct DNode{
    int data;//值域
    struct DNode * prior;//前驱指针
    struct DNode * next;//后继指针
}DLinkNode;
void createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法
void createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
    int a[3] = {1,2,3};
    DLinkNode *L = NULL;
    createListfF(L,a,3);
    traverse_list(L);
    destroy_list(L);
    return 0;
}
void createListF(DLinkNode * L ,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
    L->next = L->prior = NULL;
    for(int i = 0;i < n;i++)
    {
        DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
        s->data = a[i];
        s->next = L->next;//将新结点插入到头结点之后
        if(L->next != NULL)//L存在结点,修改前驱指针
            L->next->prior = s;
        L->next = s;
        s->prior = L;
       
    }
}
void traverse_list(DLinkNode* pHead)
{
   DLinkNode *  t = pHead->next; // t指向首结点
 
    while (t != NULL)
    {
        printf("%d ", t->data);
        t = t->next;
    }
    printf("\n");
    return;
}
void destroy_list(DLinkNode* pHead){
    DLinkNode* pre = pHead,*p = pHead->next;
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}

 上面代码,函数crateListR()无返回值,调用遍历函数traverse_list(),并不会打印结点。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct DNode{
    int data;//值域
    struct DNode * prior;//前驱指针
    struct DNode * next;//后继指针
}DLinkNode;
DLinkNode* createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法
DLinkNode* createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
    int a[5] = {1,2,3,8,9};
    DLinkNode *L = NULL;
    L = createListF(L,a,5);
    traverse_list(L);
    destroy_list(L);
    return 0;
}
DLinkNode* createListF(DLinkNode * L ,int a[],int n){
    L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
    L->next = L->prior = NULL;
    for(int i = 0;i < n;i++)
    {
        DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
        s->data = a[i];
        s->next = L->next;//将新结点插入到头结点之后
        if(L->next != NULL)//L存在结点,修改前驱指针
            L->next->prior = s;
        L->next = s;
        s->prior = L;
       
    }
    return L;
}
void traverse_list(DLinkNode* pHead)
{
   DLinkNode *  t = pHead->next; // t指向首结点
 
    while (t != NULL)
    {
        printf("%d ", t->data);
        t = t->next;
    }
    printf("\n");
    return;
}
void destroy_list(DLinkNode* pHead){
    DLinkNode* pre = pHead;
    DLinkNode* p = pHead->next;
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}

把函数crateListR()返回值改为返回DLinkNode*后(并赋给L),调用遍历函数traverse_list(),才能打印出结点。
实参L传给形参L,函数调用后形参L会被释放,但malloc()开辟的内存空间在函数调用后并不会被释放,为什么会出现这种情况呢?
星夜无尘的主页 星夜无尘 | 初学一级 | 园豆:114
提问于:2022-09-04 22:23
< >
分享
最佳答案
0

想明白了,这里犯了一个低级的错误。
形参L,经过malloc()调用分配后了一片新的堆空间,malloc()返回这片空间的基地址,那么形参L中就不再是实参中的地址了。形参L在函数调用后也确实被释放了,但通过return,把形参L地址返回(即基地址),赋值给实参L,也就能找到这些内存了。
更简单的做法是使用引用变量(可惜C语言暂不支持)。
更复杂的做法是使用二级指针,通过解除引用运算符可以达到同样效果。

星夜无尘 | 初学一级 |园豆:114 | 2022-09-05 08:04
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册