返回指向C中结构的指针

时间:2014-07-18 10:24:17

标签: c pointers struct char structure

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

中的代码
#include<stdio.h>
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;
}

4 个答案:

答案 0 :(得分:6)

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

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

  1. 使用全局变量,并返回指向该变量的指针。全局变量的生命周期是程序的生命周期。
  2. 使用static局部变量。它的生命周期也与程序相同。
  3. 在需要时动态分配结构,并返回该指针。
  4. 第1点和第2点有一个问题,那就是你只能有一个对象。如果修改该对象,则所有具有指向该单个对象的指针的位置都将看到这些更改。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

作为Joachim Pileborg answered,您不应该返回指向局部变量的指针。顺便说一句,如果使用gcc -Wall -g编译最近的GCC(例如启用几乎所有警告和调试信息),您应该收到警告。

所以在实践中,你应该决定你的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 dynamic memory allocationmanual memory managementheapmemory leaksmalloc(3)手册页上的wikipages。如果您有幸在Linux上编码,请了解valgrind

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

附录:良好的习惯

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

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

附录:使用Boehm GC

为了完整性(特别是在Linux上),只有一旦你成为专家C程序员,你可以考虑使用Boehm的保守garbage collector(见this link):那么你将GC_malloc而不是malloc,您将不需要显式free分配的指针区域。 Boehm收藏家可能(可能稍后,特别是在更大的节目中)“神奇地”为你释放记忆。但是学习垃圾收集和reference counting(可以被视为一种糟糕的GC形式,因为它管理得不好circular references)是有用的。您也可以设计自己的GC(困难任务),就像我在qishMELT中所做的那样......

答案 3 :(得分:1)

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