返回指向C中结构的指针

该程序返回一个指向结构的指针
当我打印内容时, 名称没有正确显示,其他两个变量正在正确打印。
可能是什么问题呢? 这是C中的代码

#include struct student { char name[20]; int marks; int rank; }; struct student stu; struct student *create(); void main() { struct student *ptr; ptr = create(); printf("%s\t %d\t %d\t",ptr->name,ptr->marks,ptr->rank); } struct student *create() { struct student stu = {"john",98,9}; struct student *ptrr; ptrr = &stu; return ptrr; } 

这里的问题是你正在返回一个指向局部变量的指针。 一旦定义的函数返回,局部变量就会超出范围。 这意味着返回的指针将在函数返回后指向未分配的内存。 使用该指针将导致未定义的行为

有三种方法可以解决这个问题:

  1. 使用全局变量,并返回指向该变量的指针。 全局变量的生命周期是程序的生命周期。
  2. 使用static局部变量。 它的生命周期也与程序相同。
  3. 在需要时动态分配结构,并返回该指针。

第1点和第2点有一个问题,那就是你只能有一个对象。 如果修改该对象,则指向该单个对象的所有位置都将看到这些更改。

第3点是我建议你去的方式。 问题在于,一旦完成对象,就必须释放分配的内存。

您在create function中在堆栈上本地创建了stu。 从该函数返回时,弹出堆栈,使指针指向的数据无效。

您创建一个局部变量stu ,它位于函数create() 。 在函数create()之外,此变量上的指针不正确。

正如Joachim Pileborg所回答的那样,你不应该返回一个指向局部变量的指针。 顺便说一句,如果您使用gcc -Wall -g使用最近的GCC进行gcc -Wall -g (例如,启用几乎所有警告和调试信息),您应该收到警告。

所以在实践中,你应该决定你的create返回一个堆指针,然后采用它遵循其调用者释放该指针的约定

  void main() { struct student *ptr; ptr = create(); printf("%s\t %d\t %d\t",ptr->name,ptr->marks,ptr->rank); free (ptr); } struct student *create() { struct student stu = {"john",98,9}; struct student *ptrr = malloc(sizeof struct student); if (!ptrr) { perror("malloc student"); exit(EXIT_FAILURE); } *ptrr = stu; return ptrr; } 

仔细阅读有关C动态内存分配 , 手动内存管理 , 堆 , 内存泄漏和malloc(3)手册页的wikipages 。 如果您有幸在Linux上编码,请了解valgrind 。

PS。 始终测试malloc的结果(防止失败)。 始终初始化获得的内存区域(可能用memset(3) ….清除它)。

附录:良好的习惯

您应该编译所有警告和调试信息。 如果使用GCC ,请使用gcc -Wall -g编译并改进代码,直到没有警告为止。

你肯定应该学习如何使用调试器 (在Linux, gdb ),并能够一步一步地执行程序并显示各种局部变量。

附录:使用Boehm GC

为了完整性(特别是在Linux上),只有一旦你成为专家C程序员 ,你可能会考虑使用Boehm的保守垃圾收集器 (参见此链接 ):那么你将GC_malloc而不是malloc ,你将不需要显式free分配指针区。 Boehmcollections家可能(可能稍后,特别是在更大的节目中)“神奇地”为你释放记忆。 但是学习垃圾收集和引用计数 (可以被视为GC的不良forms,因为它不管理良好的循环引用 )是有用的。 您也可以设计自己的GC(困难的任务),就像我在qish或MELT中所做的那样 ……