向前声明

时间:2014-08-14 20:52:42

标签: c struct forward-declaration

如何为每个函数提供结构声明,如下所示:

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

struct additionalVariables;

struct container {
    int am;
    int bm;

    struct additionVariables *variables;
};

void foo(void) {
    struct container myContainer;

    struct additionalVariables {
        int x;
        int y;
    };

    myContainer.variables = malloc(sizeof(struct additionVariables));

    myContainer.variables->x = 5;
    myContainer.variables->y = 6;

    free(myContainer.variables);
}

void bar(void) {
    struct container myContainer;

    struct additionalVariables {
        char a;
        int b;
        int x;
    };

    myContainer.variables = malloc(sizeof(struct additionVariables));

    myContainer.variables->a = 5;
    myContainer.variables->b = 6;
    myContainer.variables->x = 7;

    free(myContainer.variables);
}

int main(void) {
    foo();
    bar();

    return 0;
}

我宁愿不必演员。不同的additionVariables结构必须能够具有相同的名称,例如foo和bar都需要x的属性。

4 个答案:

答案 0 :(得分:0)

您可以做的是制作container结构的本地版本。

void foo(void) {
    struct {
        int am;
        int bm;
        struct additionVariables {
            int x, y;
        } *variables;
    } myContainer;

    myContainer.variables = malloc(sizeof(struct additionVariables));
    myContainer.variables->x = 5;
    myContainer.variables->y = 6;

    free(myContainer.variables);
}

然后,如果需要传递它,可以使用void指针声明container结构。

struct container {
    int am;
    int bm;
    void *variables;
};

如果你想将对象传递给其他函数,你仍然需要进行强制转换:

DoSomeThingWithContainer((struct container *)&myContainer);

答案 1 :(得分:0)

可以使container在您的主要内容中显示,additionalVariables显然不可以。{ 我把它分成几个文件,它编译(更重要的是链接)确定。

<强>的main.c

#include "foobar.h"

int main(void) {
    foo();
    bar();

    return 0;
}


foobar.h中

void foo(void);
void bar(void);

struct additionalVariables;

struct container {
    int am;
    int bm;

    struct additionalVariables* variables;
};


foo.c的

#include "foobar.h"

#include <stdlib.h>

struct additionalVariables {
    int x;
    int y;
};

void foo(void) {
    struct container myContainer;

    myContainer.variables = (additionalVariables*)malloc(sizeof(struct additionalVariables));

    myContainer.variables->x = 5;
    myContainer.variables->y = 6;

    free(myContainer.variables);
}


bar.c

#include "foobar.h"

#include <stdlib.h>

struct additionalVariables {
    int x;
    char a;
    int b;
};

void bar(void) {
    struct container myContainer;

    myContainer.variables = (additionalVariables*)malloc(sizeof(struct additionalVariables));

    myContainer.variables->a = 5;
    myContainer.variables->b = 6;
    myContainer.variables->x = 7;

    free(myContainer.variables);
}

答案 2 :(得分:0)

这就是我如何解决所提出的问题:

struct container {
    int am;
    int bm;
};

您还没有解释为什么需要抽象指针。所以,我删除了它。

void foo(void) {
    struct mycontainer {
        struct container base;
        int x;
        int y;
    } myContainer;

    myContainer.x = 5;
    myContainer.y = 6;
}

此处,foo()声明其容器的本地版本,添加其他字段。 myContainer.base的地址可以传递给任何想要struct container *的函数,它的地址与myContainer的指针相同。由于我们不再处理指针,因此无需拨打malloc()free()

void bar(void) {
    struct mycontainer {
        struct container base;
        char a;
        int b;
        int x;
    } myContainer;

    myContainer.a = 5;
    myContainer.b = 6;
    myContainer.x = 7;
}

bar()也可以创建自己的版本。

int main(void) {
    foo();
    bar();

    return 0;
}

然而,我有一种感觉,你真正想要的是dynamic dispatching

答案 3 :(得分:0)

使用所有分支中可用的所有名称在外部声明结构:

struct additionalVariables {
    int x;
};

struct container {
    int am;
    int bm;
    struct additionalVariables *variables;
};

然后通过将原始作为更大结构的第一个元素放置在每个函数中来扩展它:

void foo(void) {
    struct container myContainer;

    struct additionalVariablesFoo {
        struct additionalVariables base;
        int y;
    };

    myContainer.variables = malloc(sizeof(struct additionVariablesFoo));

    myContainer.variables.x = 5;
    (struct AdditionalVariablesFoo *)&(myContainer.variables)->y = 6;

    free(myContainer.variables);
}

由于总是可以转换为第一个元素的类型,因此您可以在不需要演员的情况下访问函数外部的x字段,但需要付出代价演员在初始时到达函数中的y字段(显然,如果你只是通过struct AdditionalVariablesFoo *类型的临时变量初始化它,你也不需要这个演员)。在函数外部,扩展对象将被视为具有第一个元素的类型,即声明共享名称的基础。