【问题标题】:returning pointer to a structure in C返回指向C中结构的指针
【发布时间】:2014-09-09 11:01:39
【问题描述】:

这个程序返回一个指向结构的指针
当我打印内容时,name 没有正确显示,而其他两个变量正在正确打印。
可能是什么问题呢? 这是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;
}

【问题讨论】:

    标签: c pointers struct char structure


    【解决方案1】:

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

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

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

    第 1 点和第 2 点的问题在于,您只能拥有一个对象。如果您修改该对象,那么您拥有指向该单个对象的指针的所有位置都会看到这些更改。

    第 3 点是我推荐你的方式。这样做的问题是,一旦你完成了对象,你必须释放你分配的内存。

    【讨论】:

    • 局部变量超出范围我在问这个问题时也有同样的问题。但我不明白为什么它部分有效,部分无效.谢谢。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        因此,在实践中,您应该决定您的create 返回一个堆指针,然后遵循调用者释放该指针的约定。 p>

         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) 手册页上的维基页面。如果你有幸在 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 中所做的那样......

        【讨论】:

        • 是的。动态地为结构创建内存是出路。感谢您的代码。
        • 嗯,实际上(正如 OP 所证明的那样),您可以返回一个指向局部变量的指针。这样做并没有多大好处。
        猜你喜欢
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 1970-01-01
        • 2014-12-30
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        • 2021-07-14
        相关资源
        最近更新 更多