【问题标题】:Passing a Structure by reference to a function that will dynamically create and fill a array of structures通过引用将动态创建和填充结构数组的函数传递结构
【发布时间】:2018-01-16 05:39:11
【问题描述】:

我想将一个结构指针传递给一个函数,该函数将在传递的结构指针指向的位置动态创建一个结构数组。我能够成功地创建和填充结构数组,但是当尝试使用传递的指针在调用函数中打印数据时,会给我一个垃圾值。请帮助我知道为什么我的结构指针指向垃圾以及如何正确访问我的数据。

以下只是一些示例代码,用于演示如何使用 malloc 和 realloc 传递和动态填充结构。这是不正确的方法:

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

struct student 
{
    int id;
    char name[20];
    float percentage;
};

void func(struct student *record);

int main() 
{
    struct student *record = NULL;

    record = (struct student *)malloc(sizeof(struct student));

    func(record);

    if(record != NULL)
    {
        for(int i=0; i<2; i++)
        {
            printf(" 1 Id is: %d \n", record[i].id);
            printf(" 1 Name is: %s \n", record[i].name);
            printf(" 1 Percentage is: %f \n", record[i].percentage);
            printf("\n");
        }
    }
    else
    {
        printf("record pointer is null");
    }

    return 0;
}

void func(struct student *record1)
{
    for(int i=0; i<2; i++)
    {
        if(i)
        {
            record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));
        }
        record1[i].id=1;
        strcpy(record1[i].name, "Raju");
        record1[i].percentage = 86.5;
    }
}

以下是使用双指针的类似示例,这是执行此操作的正确方法:

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

struct student 
{
    int id;
    char name[20];
    float percentage;
};

void func(struct student **record);

int main() 
{
    struct student *record = NULL;

    func(&record);

    if(record != NULL)
    {
        for(int i=0; i<2; i++)
        {
            printf(" 1 Id is: %d \n", record[i].id);
            printf(" 1 Name is: %s \n", record[i].name);
            printf(" 1 Percentage is: %f \n", record[i].percentage);
            printf("\n");
        }
    }
    else
    {
        printf("record pointer is null");
    }

    free(record);

    return 0;
}

void func(struct student **record1)
{
    *record1 = (struct student *)malloc(sizeof(struct student));
    for(int i=0; i<2; i++)
    {
        if(i)
        {
            *record1 = (struct student *)realloc(*record1,sizeof(struct student)*(i+1));
        }
        (*record1)[i].id=1;
        strcpy((*record1)[i].name, "Raju");
        (*record1)[i].percentage = 86.5;
    }
}

【问题讨论】:

  • 如果您使用 C++ 编程,为什么要使用 mallocfreerealloc?这里的“正确”解决方案是使用std::vector&lt;TEST_STRUCT&gt;
  • @Someprogrammerdude 我主要尝试基于 C 的解决方案,但如果需要我也可以使用 C++ 概念,我会研究向量。
  • @O'Neil 由于我发布的示例存在很多问题,因此我将其替换为新的更简单的示例,其中一个正在运行。因此,既然您提到 ap_test 是我的指针测试的副本,那么如果我需要它指向与原始指针相同的位置,我应该怎么做。我曾尝试使用双指针,但我收到调试断言失败消息。令人惊讶的是,在我提供的新示例中,它甚至可以使用指针的副本。
  • record1 => *record1realloc 内。使用临时指针来做所有事情并最终分配*record1 = that_pointer; 不太容易出错。关于令人惊讶的复制结果,我猜 realloc 在重新分配时没有更改地址。
  • @O'Neil 确保在您的文章中解释为什么传递 struct student *record 不起作用。 record 的地址在mainfunc 之间是如何分开和不同的,以及为什么需要传递record地址

标签: c arrays pointers data-structures


【解决方案1】:

您的第一个解决方案,

record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));

只要 realloc 不必移动指针就可以工作 也就是说,realloc 只是将它之前给record1 的内存区域扩展了。如果在稍后的某个阶段,realloc 需要给你另一块内存,那么main 中的早期指针record 将变为无效,现在可以包含你的“垃圾”。

正如您所想,您需要一个双指针才能看到 main 中更改的指针。你快到了,只是一个错字:

*record1 = (struct student *)realloc(record1,sizeof(struct student)*(i+1));

在上面的行中,record1 的第二次出现也必须被取消引用,所以*record1 因为你必须给realloc 原始指针。

哦,不要强制转换 malloc 的结果!虽然编译器没有抱怨,但它可能会导致未来的问题。

【讨论】:

  • 你能告诉我为什么强制转换 malloc 不好。此外,当我尝试删除第二个示例中的类型转换并编译代码时,我收到错误消息:“void *”类型的值不能分配给“student *”类型的实体。那么在我的情况下,如何避免类型转换 malloc 的返回值。
  • @Ghos3t:这是一个不同的问题,它已经有了很好的答案。请参阅Do I cast the result of malloc?,以及接受的答案。
  • 来自 WedaPashi 的良好参考。但是当你的编译器抱怨那个 void 指针时,那么你正在编译为 C++,而不是 C。
猜你喜欢
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多