【问题标题】:Resolve circular typedef dependency?解决循环 typedef 依赖?
【发布时间】:2010-10-27 15:59:36
【问题描述】:

在对这些结构进行类型定义时,解决以下循环依赖的最佳方法是什么?
请注意 C 语言标记 - 我正在寻找标准 gcc C 中的解决方案。

typedef struct {
    char* name;
    int age;
    int lefthanded;
    People* friends;
} Person;

typedef struct {
    int count;
    int max;
    Person* data;
} People;

【问题讨论】:

    标签: c circular-dependency


    【解决方案1】:

    答案在于声明和定义的区别。您试图在同一步骤中声明和定义(在通过 typedef 的新类型的情况下)。您需要将它们分解为不同的步骤,以便编译器提前知道您在说什么。

    typedef struct Person Person;
    typedef struct People People;
    
    struct Person {
        char* name;
        int age;
        int lefthanded;
        People* friends;
    };
    
    struct People {
        int count;
        int max;
        Person* data;
    };
    

    注意顶部添加的两个“空”类型定义(声明)。这告诉编译器新类型 Person 的类型是“struct Person”,因此当它在 struct People 的定义中看到它时,就知道它的含义了。

    在您的特定情况下,您实际上可以只预先声明 People typdef,因为这是在定义之前使用的唯一类型。当您开始定义 struct People 时,您已经完全定义了 Person 类型。因此,以下方法也可以使用,但不推荐,因为它很脆弱:

    typedef struct People People;
    
    typedef struct {
        char* name;
        int age;
        int lefthanded;
        People* friends;
    } Person;
    
    struct People {
        int count;
        int max;
        Person* data;
    };
    

    如果你交换结构定义的顺序(将 struct People 移动到 Person 的 typedef 之上),它将再次失败。这就是它脆弱的原因,因此不推荐。

    请注意,如果您包含指定类型的结构而不是指向它的指针,则此技巧不起作用。因此,例如,以下 不会编译

    typedef struct Bar Bar;
    
    struct Foo
    {
        Bar bar;
    };
    
    struct Bar
    {
        int i;
    };
    

    上面的代码给出了一个编译器错误,因为当它试图在 struct Foo 的定义中使用 Bar 类型时它是不完整的。换句话说,它不知道要为结构成员'bar'分配多少空间,因为那时它还没有看到结构bar的定义。

    这段代码会编译

    typedef struct Foo Foo;
    typedef struct Bar Bar;
    typedef struct FooBar FooBar;
    
    struct Foo
    {
        Bar *bar;
    };
    
    struct Bar
    {
        Foo *foo;
    };
    
    struct FooBar
    {
        Foo     foo;
        Bar     bar;
        FooBar  *foobar;
    };
    

    即使使用 Foo 和 Bar 中的循环指针,这也有效,因为类型 'Foo' 和 'Bar' 已预先声明(但尚未定义),因此编译器可以构建指向它们的指针。

    当我们开始定义 FooBar 时,我们已经定义了 Foo 和 Bar 的大小,因此我们可以在其中包含实际的对象。我们还可以包含一个指向 FooBar 类型的自引用指针,因为我们已经预先声明了该类型。

    请注意,如果您将 struct FooBar 的定义移到 struct Foo 或 Bar 的定义之上,则由于与上一个示例相同的原因(不完整类型),它将无法编译。

    【讨论】:

      【解决方案2】:

      前向声明结构之一:

      
      struct people;
      
      typedef struct {
        /* same as before */
        struct people* friends;
      } Person;
      
      typedef struct people {
        /* same as before */
      } People;
      

      【讨论】:

      • 有人应该提到你必须写 typedef struct people { .... } People;然后。所以,它和以前不完全一样(恕我直言,无论如何,另外给出明确的标签名称是个好主意)
      • 你说得对,只是懒得回去编辑答案,现在就可以了。
      • 在 struct Person 中我们不能声明 struct people friends 而不是指针吗?它为我抛出错误。例如:struct people;typedef struct { struct people friends;} Person;typedef struct people { Person person;};
      • 不,考虑一下。你的递归在哪里结束?
      • 值得注意的是,使用指向前向声明结构的指针是使其正常工作的唯一方法
      【解决方案3】:

      关于可读性:

      typedef struct Foo_ Foo;
      typedef struct Bar_ Bar;
      
      struct Foo_ {
          Bar *bar;
      };
      
      struct Bar_ {
          Foo *foo;
      };
      

      完全避免typedef struct 可能是个好主意;

      【讨论】:

        【解决方案4】:

        由于Person 只是想要一个指向People 的指针,所以只需预先声明后者就可以了:

        typedef struct People People;
        

        然后将第二个声明更改为仅使用 struct 标记进行声明,如下所示:

        struct People {
            int count;
            int max;
            Person data[];
        };
        

        【讨论】:

          【解决方案5】:
          struct _People;
          
          typedef struct {
              char* name;
              int age;
              int lefthanded;
              struct _People* friends;
          } Person;
          
          struct _People {
              int count;
              int max;
              Person data[1];
          };
          

          注意:Person data[]; 是标准的吗?

          【讨论】:

          • 具有空 [] 的灵活数组成员是 C99 及更高版本的标准。它必须是具有至少一个其他成员的结构类型的最后一个元素。
          【解决方案6】:
          struct People_struct;
          
          typedef struct {
              char* name;
              int age;
              int lefthanded;
              struct People_struct* friends;
          } Person;
          
          typedef struct People_struct {
              int count;
              int max;
              Person data[];
          } People;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-11-12
            • 1970-01-01
            • 1970-01-01
            • 2013-02-04
            • 1970-01-01
            相关资源
            最近更新 更多