【问题标题】:Scoped forward declaration范围前向声明
【发布时间】:2014-08-14 20:52:41
【问题描述】:

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

#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 的属性。

【问题讨论】:

  • 我想你正在寻找union
  • variables 成员使用void *
  • 不能使用联合,因为我需要以 myContainer.variables.x 的形式访问它(因此它必须使用 C11 匿名继承),但两者都需要一个名为 x 的属性,所以这不起作用.我的条件非常具体,我不确定这是否可能。寻找最接近的答案。

标签: c struct forward-declaration


【解决方案1】:

您可以做的是制作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);
}

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

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

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

DoSomeThingWithContainer((struct container *)&myContainer);

【讨论】:

    【解决方案2】:

    可以使 container 在您的主目录中可见,但 additionalVariables 显然不能。
    我将它拆分为几个文件,它可以编译(更重要的是链接)。

    ma​​in.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);
    }
    

    【讨论】:

      【解决方案3】:

      这就是我解决问题的方法:

      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

      【讨论】:

        【解决方案4】:

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

        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 字段,但代价是需要转换才能获得 @987654324 @ 初始化时函数内的字段(显然,如果您只是通过 struct AdditionalVariablesFoo * 类型的临时变量对其进行初始化,那么您也不需要此强制转换)。在函数之外,扩展对象将被视为具有其第一个元素的类型,即声明共享名称的基类。

        【讨论】:

          猜你喜欢
          • 2016-07-14
          • 2015-05-26
          • 2016-05-17
          • 1970-01-01
          • 2017-08-30
          • 1970-01-01
          • 1970-01-01
          • 2016-10-11
          • 1970-01-01
          相关资源
          最近更新 更多