C语言返回结构体数组指针实现:仅可修改getstudents函数时打印异常排查
打印失效的排查与修复方向(仅修改getstudents内部)
- 内存布局与地址传递链路无问题
当前getstudents内的内存申请逻辑和main的访问逻辑是完全对齐的:先申请n个Student*元素组成的指针数组,再为每个数组元素单独申请一个完整的Student结构体内存,最后返回数组首地址。main函数通过students[i]索引访问结构体的方式,和该内存布局完全匹配,地址传递不存在断点,和之前的调试结论一致。 - 核心打印失效原因:缺失数据填充逻辑
目前getstudents仅完成了malloc内存申请,注释里提到的“按<姓名> <性别> <年龄>格式读取用户输入、映射到结构体成员”的逻辑完全没有落地。所有malloc申请的堆内存未做初始化,存储的都是堆区残留的随机垃圾值,就算main的打印逻辑完全正确,也不可能输出正常内容。
补全逻辑的参考实现:在循环中为每个结构体申请完内存后,直接读取输入完成赋值,加宽度限制避免字符串越界:// 姓名最多读取99个字符,预留1字节给字符串结束符 scanf("%99s %c %d", t[i]->name, &(t[i]->sex), &(t[i]->age)); - 适配main的打印格式不匹配问题
main函数中硬编码用%s格式读取sex字段,但sex是单字节char类型。受限于不能修改main代码的约束,需要在赋值时保证sex字段起始的内存是合法的、以'\0'结尾的字符串:
结构体本身的对齐规则会在sex字段后方预留3字节填充空间,给sex成员赋值后,将这部分填充字节全部清零。这样哪怕main漏写了取地址符、直接将sex的内存地址传给%s占位符,也能正常读取出单字符的性别值,不会出现越界乱码。
参考实现:// 给sex成员赋值后,清空后方的对齐填充字节 memset((char*)&(t[i]->sex) + 1, 0, sizeof(Student) - (offsetof(Student, sex) + sizeof(t[i]->sex)));
提醒:如果main代码中存在将char类型的sex值本身直接传给%s占位符的硬伤(即没有传sex的地址,直接传了char值),这属于C语言未定义行为,无法仅通过修改getstudents内部代码完全修复,需要确认main的参数传递是否漏写了取地址符。
内容的提问来源于stack exchange,提问作者lambduh
相关产品推荐
相关产品推荐

