You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言单链表先调用insrt_frnt不生效、先调用insrt_end正常的原因是什么?

C语言单链表插入逻辑异常问题解析

核心错误总览

你的代码存在3个致命逻辑/语法错误,三者共同导致了「先调用头插崩溃、先调用尾插能正常运行」的现象:

  • 内存申请大小错误,访问非法内存
  • 头插函数节点初始化缺失,产生野指针
  • 尾插函数遍历逻辑错误,存在空指针解引用风险

错误细节说明

1. 内存申请大小错误

你两处malloc的参数都写的是sizeof(struct node *),这里申请的是结构体指针的大小(32位系统占4字节,64位系统占8字节),远小于struct node结构体本身需要的空间。后续给data、next成员赋值时会访问到不属于当前节点的内存,属于未定义行为,运行结果完全随机,刚好先调用尾插时非法访问没触发系统内存保护,就看起来能正常运行,先调用头插时触发保护就直接崩溃。
正确写法应该是申请结构体本身的大小:

// 旧写法(错误)
struct node *temp = (struct node *) malloc(sizeof(struct node *));
// 新写法(正确)
struct node *temp = (struct node *) malloc(sizeof(struct node));

2. 头插函数初始化逻辑缺失

你的insrt_frnt函数只有head != NULL时才给temp->next赋值,当第一次调用头插、head为NULL时,没有给temp->next赋值,导致temp->next是野指针,后续遍历链表到这里时就会访问非法内存崩溃。
而你先调用尾插时,尾插函数会主动给新节点的next赋值为NULL,就不会出现野指针问题,所以看起来能正常运行。
正确的头插逻辑可以直接简化,不需要单独判断head是否为空:

struct node * insrt_frnt(struct node *head){
    struct node *temp = (struct node *) malloc(sizeof(struct node));
    printf("\n Enter data:");
    scanf("%d", &temp->data);
    // 统一给新节点的next赋值,不管head是否为空
    temp->next = head;
    // 新的头节点就是temp
    return temp;
}

3. 尾插函数遍历逻辑错误

你尾插函数的循环条件是while(ptrr != NULL),跳出循环时ptrr已经是空指针,此时执行ptrr->next = neww属于空指针解引用,100%会触发非法访问崩溃。你之前先调用尾插能跑是因为第一次调用时head为NULL,直接走了if(head == NULL)的分支,没执行到后面的循环逻辑而已,只要链表有1个以上节点再调用尾插就会直接崩溃。
正确的遍历逻辑应该是找到最后一个节点(即ptrr->next == NULL时停止):

struct node * insrt_end(struct node *head){
    struct node *ptrr = head;
    struct node *neww = (struct node *) malloc(sizeof(struct node));

    printf("\n Enter data:");
    scanf("%d", &neww->data);
    neww->next = NULL;

    if(head == NULL){
        head = neww;
    } else {
        // 找最后一个节点,不是找空指针
        while(ptrr->next != NULL){
            ptrr = ptrr->next;
        }
        ptrr->next = neww;
    }
    return head;
}

修正后完整代码

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

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

struct node * insrt_frnt(struct node *head){
    struct node *temp = (struct node *) malloc(sizeof(struct node));
    printf("\n Enter data:");
    scanf("%d", &temp->data);
    temp->next = head;
    return temp;
}

struct node * insrt_end(struct node *head){
    struct node *ptrr = head;
    struct node *neww = (struct node *) malloc(sizeof(struct node));

    printf("\n Enter data:");
    scanf("%d", &neww->data);
    neww->next = NULL;

    if(head == NULL){
        head = neww;
    } else {
        while(ptrr->next != NULL){
            ptrr = ptrr->next;
        }
        ptrr->next = neww;
    }
    return head;
}

void display(struct node *head){
    while(head != NULL){
        printf("%d\n", head->data);
        head = head->next;
    }
}


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

    head = insrt_frnt(head);
    head = insrt_end(head);
    display(head);

    // 实际使用时记得补充链表内存释放逻辑避免内存泄漏
    return 0;
}

内容的提问来源于stack exchange,提问作者Raghav Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 05:36:03