返回指向结构指针的指针

时间:2017-03-24 16:46:01

标签: c pointers struct

我正在研究一个有多个结构的数据库。我已经定义了一个从csv文件加载数据并将每一行存储为结构的函数。我使用双指针存储它们,因此一个指针指向每个结构变量的多个指针。该函数确实正确返回双指针,但是我收到一个警告:从不兼容的指针类型返回。

我的代码如下:

struct part** loadParts(char* fileName, int m)
{
    typedef struct part
    {
        int id;
        int cost;
    } Part;
    FILE* fptr = fopen(fileName, "r");
    //creat pointer to array of pointers to part structs
    Part** parts;
    parts = malloc((nParts) * sizeof(Part *));
    //length of one line
    char line[1000];

    //while new items can be added
    int i;
    i=0;
    while (fgets(line, sizeof(line), fptr)!= NULL)
    {
            parts[i] = malloc(sizeof(Part));
            //get id
            int id = atoi(strtok(line, ";"));
            parts[i]->id = id;
            // get cost
            int id = atoi(strtok(line, ";"));
            parts[i]->cost = cost;
    i++;
    }
    fclose(fptr);
    return parts;
}

有人知道为什么会出现此警告吗?非常感谢提前!

1 个答案:

答案 0 :(得分:0)

你有大纲:

struct part** loadParts(char* fileName, int m)
{
    typedef struct part
    {
        int id;
        int cost;
    } Part;
    …
    Part** parts;
    …
    parts = …
    …
    return parts;
}

没有警告就无法编译。根据定义,函数签名中使用的struct part与函数内定义的struct part完全无关。因此,您将返回指向函数中某种类型的指针,该函数期望返回指向其他类型的指针,即使这些类型可能拼写为struct part。甚至没有办法让你的代码摆脱困境。

如注释中所示,结构定义必须在函数定义之前(可能在任何声明之前 - 并且通常在使用结构的任何地方使用的头文件中)都在函数之外。

因此,解决代码的一种方法是:

typedef struct part
{
    int id;
    int cost;
} Part;

struct part **loadParts(char *fileName, int m)
{
    …
    Part **parts;
    …
    parts = …
    …
    return parts;
}

在这种情况下,您可以让函数返回Part **

但是,除非您有一个包含结构定义的标头,否则现在应将该函数定义为static。如果没有标题,则无法(可靠地)访问其他源文件中的结构类型。 (可以通过两次编写代码来完成,但是编写代码两次应该是令人厌恶的 - 在你完成输入或复制'n'pasting,第二个副本之前,它将成为维护责任。)

您可能正在处理不透明类型;此文件外部的代码不需要知道结构细节。那是合法的;它甚至可以(非常)有益。不过,你只需要一种不同的写作方式:

部首:

typedef struct part Part;
extern struct part **loadParts(char *fileName, int m);

如果您决定不公开名称Part,则可以改为使用此标题:

struct part;
extern struct part **loadParts(char *fileName, int m);

第一行显示“有struct part类型,但如果您需要,将在稍后提供详细信息”。第二个声明函数返回指向struct part值的指针。 extern是可选的;我用它 - 很多人没有。在此代码中,第一行是可选的。但是,如果您将extern int num_parts(struct part **list);作为函数,则需要在loadParts()声明后显示,或者您需要struct part;行以确保原型中的类型不是新。

来源:

struct part 
{
    int id;
    int cost;
};

struct part **loadParts(char *fileName, int m)
{
    …
    Part **parts;
    …
    parts = …
    …
    return parts;
}

您需要担心标题中的标题保护以确保幂等性。 (在这个例子中,没有自包含的问题,但是你也应该确保你的标题是自包含的 - 如果你搜索的话,SO上有多个问题可以解释这些术语。)