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

C语言如何引用结构体内部嵌套的另一结构体指针

问题修复说明

直接崩溃原因

  • 调用scanf读取年龄字段时未传入地址:p[i].pet_age->years是int类型的值,scanf接收int参数需要传入对应变量的指针,正确写法是&(p[i].pet_age->years),月份字段同理,这是程序输入月份后崩溃的直接原因。

其他隐藏逻辑错误

  • 函数参数传递错误:C语言是值传递,你在addPet函数内修改形参p的指向(malloc/realloc操作)不会影响main函数里的petarray变量,导致主函数永远拿不到正确的数组地址。
  • 首次调用判断写错:if(i=1)是赋值操作,永远返回真,每次调用addPet都会重新申请内存,原有数据全部丢失还会造成内存泄漏,应该改成if(i==1)的相等判断。
  • 字符串内存分配不足:sex字段只分配了1字节的内存,字符串结尾需要额外1字节存\0,至少要分配2字节,否则scanf写入会越界。
  • 内存分配大小写错:首次malloc(k*sizeof(p))里p是指针类型,sizeof(p)得到的是指针的大小,不是pet结构体的大小,应该改成sizeof(pet)或者sizeof(*p)。
  • pet_age分配方式不规范:malloc(sizeof(int)*2)虽然刚好匹配age结构体的大小,但是可读性差,后续如果结构体修改很容易出问题,建议改成malloc(sizeof(age))。
  • 数组下标浪费:全局计数器i从1开始,数组下标0的位置永远被浪费,建议从0开始计数。

提示:建议后续功能实现完成后,注意补充边界校验逻辑,避免非法输入导致程序崩溃,下述修复代码已在退出流程中加入了基础的内存释放逻辑,避免内存泄漏

修复后完整可运行代码

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

typedef struct age
{
    int years, months;
} age;

typedef struct pet
{
    int id;
    char* sex;
    char* breed;
    age* pet_age;
} pet;

int i = 0; // 计数器从0开始,不浪费数组空间
int k = 10;   // 默认初始容量

// 改成传二级指针,才能修改main里的petarray的指向
void addPet(pet **p){
    // 首次调用初始化数组
    if(i == 0){
        *p = malloc(k * sizeof(pet));
        if(!*p){
            printf("\n内存分配失败...");
            exit(0);
        }
    }
    // 给当前pet的各个成员分配内存
    (*p)[i].sex = malloc(sizeof(char)*2); // 存单个字符加结束符\0
    (*p)[i].breed = malloc(sizeof(char)*20);
    (*p)[i].pet_age = malloc(sizeof(age));
    
    (*p)[i].id = i+1;    // 自增ID从1开始,符合用户习惯
    printf("\n宠物ID:%d\n", (*p)[i].id);
    
    printf("输入宠物品种:");
    scanf("%s", (*p)[i].breed);
    
    printf("输入宠物性别(M/F):");
    scanf("%s", (*p)[i].sex);
    
    printf("输入宠物年龄(年):");
    scanf("%d", &((*p)[i].pet_age->years)); // 传入地址
    printf("已输入年份:%d\n", (*p)[i].pet_age->years);
    
    printf("输入宠物年龄(月):");
    scanf("%d", &((*p)[i].pet_age->months)); // 传入地址
    printf("已输入月份:%d\n", (*p)[i].pet_age->months);
    
    i++;
    
    // 容量不足扩容
    if(i == k){
        k += 10;
        *p = realloc(*p, k * sizeof(pet));
        if(!*p){
            printf("\n内存扩容失败...");
            exit(0);
        }
    }
}

int main(int argc, char *argv[]) {
    int choice;
    pet *petarray = NULL; // 初始化野指针为NULL
    
    while(1){
        printf("\n\n 菜单:");
        printf("\n=========");
        printf("\n1. 新增宠物信息");
        printf("\n2. 根据ID删除宠物记录");
        printf("\n3. 根据品种查询宠物记录");
        printf("\n4. 修改品种名称");
        printf("\n5. 退出\n\n");
        scanf("%d", &choice);
        switch(choice)
        {
            case 1:
                addPet(&petarray); // 传入指针的地址
                break;
            case 2:
                // 后续实现删除逻辑
                break;
            case 3:
                // 后续实现查询逻辑
                break;
            case 4:
                // 后续实现修改逻辑
                break;
            case 5:
                // 退出前释放所有申请的内存,避免内存泄漏
                for(int j=0;j<i;j++){
                    free(petarray[j].sex);
                    free(petarray[j].breed);
                    free(petarray[j].pet_age);
                }
                free(petarray);
                printf("程序退出...");
                exit(0);
        }
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:15:02