【问题标题】:C return struct pointerC返回结构指针
【发布时间】:2015-12-20 02:28:29
【问题描述】:

假设我有一个这样的结构:

struct Person {
    int age;
    char *name;
    Person *next_ptr;
}

现在我有一个函数可以生成 2 个人并返回指向第一个结构的指针:

Person *GetPerson(){
char[5] p1name = "John";
char[4] p2name = "Bob";

struct Person *p1;
struct Person *p2;

p2 = malloc(sizeof(struct Person));
strcpy(p2.name, p2name);
p2->age = 25;

p1 = malloc(sizeof(struct Person));
strcpy(p1.name, p1name);
p1->age = 20;
p1->next_ptr = p2;

return p1;
}

以及提取这两个Person的函数的用法。

struct Person *person = malloc(sizeof(struct Person));
person = GetPerson();
int person1age = person.age; // Get age
char person1name[4] = person.name; // Get name
int *person2_ptr = person.next_ptr; // Extract the person 2 pointer

struct Person *person2 = malloc(sizeof(struct Person));
person2 = (*person2_ptr);
char person2name[4] = person2.name; // gets person 2 name
int person2age = person2; // get person 2 age

我希望我能清楚地说明我想要做什么。有人可以告诉我正确的实现方法吗?

【问题讨论】:

  • p1 是堆栈上的struct Person。函数GetPerson 被声明为返回一个Person *(推测Person 是struct Person 的typedef),它应该在堆上分配并返回。稍微阅读一下,您实际上是在分配 p1 和 p2,因此将它们调整为 struct Person *。还发布一个完整的程序,并准确说明什么不起作用以及为什么
  • 在名称后用括号声明字符数组。还要确保为字符串上的空终止符留出空间! char p1name[5] = "John"
  • char p1name[5] 要求 6 个字符,因为 0 索引?
  • 没有。它要求 5 个字节。
  • 您没有为名称字符串分配空间。你没有办法返回第二个结构指针。

标签: c pointers struct


【解决方案1】:

很遗憾,您的代码中有很多错误。

1。 在 C 中,与 C++ 不同,每次要创建 struct Person 的实例时,都必须说 struct Person,而不是 Person

2。 在 C 中,声明大小为 5 的 char 数组的方式是 char p1name[5]; 而不是 char[5] p1name;

  1. GetPerson() 的主体内,p1p2 被声明为指针,这意味着strcpy(p1.name,p1name); 实际上应该是strcpy(p1->name,p1name); 甚至strcpy((*p1).name,p1name);,如果你愿意的话。

更严重的问题:

  1. 您必须注意,当您为struct Person 的实例动态分配内存时,您不会自动为char * name; 分配内存;因为这个调用strcpy(p1->name,p1name); 会失败。您可以保留 char* 并为其动态分配内存,但为了简单起见,我建议您只选择一个相当大的 char 数组。

  2. 记住GetPerson()struct Person 的实例分配内存并返回一个指针。现在在你的主要功能中你有:

    struct Person *person = malloc(sizeof(struct Person)); //allocating memory in main
    person = GetPerson();  // you just leaked the memory you allocated in main
    

    您分配了两次内存。这不会导致您的程序崩溃,但会导致您需要避免的“内存泄漏”。你总是想free()动态分配内存。

把这些放在一起,你就得到了:

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

struct Person {
    int age;
    char name[256];
    struct Person *next_ptr;
};

struct Person * GetPerson(){
    char p1name[5] = "John";
    char p2name[4] = "Bob";

    struct Person *p1;
    struct Person *p2;

    p2 = malloc(sizeof(struct Person));
    strcpy(p2->name, p2name);
    p2->age = 25;
    p2->next_ptr=NULL;

    p1 = malloc(sizeof(struct Person));
    strcpy(p1->name, p1name);
    p1->age = 20;
    p1->next_ptr = p2;

    return p1;
}

int main()
{
    struct Person * tmp=GetPerson();

    printf(tmp->name); //prints John
    printf("\n");
    printf(tmp->next_ptr->name); //prints Bob
    printf("\n");
    free(tmp);

    return 0;
}

请注意,这在逻辑上仍然不是很好的代码,但它没有错误。

【讨论】:

    【解决方案2】:
    struct Person p1;
    

    应该是指针:

    struct Person *p1;
    

    p2 也是如此。

    那么当你想访问结构中的字段时,你不能这样做:

    p2.age = 25;
    

    相反,您必须使用:

    p2->age = 25;
    

    因为p2 现在是指针而不是实例。以上等价于:

    (*p2).age = 25;
    

    【讨论】:

      【解决方案3】:

      您的主要问题是您没有为包含人名本身的字符串分配空间。所以当你这样做时

      p2 = malloc(sizeof(struct Person));
      strcpy(p2->name, p2name);
      

      p2->name 并没有真正指向任何重要的地方,事情会失败。您在这里有 2 个选项,一个是使用 2 个 malloc 分别对名称的结构和足够的空间进行 malloc:

      p2 = malloc(sizeof(struct Person));
      p2->name = malloc(60); // deemed sufficient for name
      strcpy(p2->name, p2name);
      

      或者,您将 name 声明为一个数组,在这种情况下,它将通过将结构定义更改为:

      struct Person {
          int age;
          char name[60];
          Person *next_ptr;
      }
      

      在这种情况下,原始 malloc 也会为 name 分配空间。任何一个都应该工作。对 p2 所说的一切也适用于 p1。

      【讨论】:

        猜你喜欢
        • 2017-08-22
        • 2017-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-09
        • 1970-01-01
        • 1970-01-01
        • 2022-06-15
        相关资源
        最近更新 更多