[ACCEPTED]-Resolve circular typedef dependency?-circular-dependency

Accepted answer
Score: 49

The answer lies in the difference between 46 declaration and definition. You are attempting 45 to declare and define in the same step (in 44 the case of a new type via typedef). You 43 need to break these up into different steps 42 so the compiler knows what you are talking 41 about in advance.

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;
};

Note the addition of the 40 two 'empty' typedefs at the top (declarations). This 39 tells the compiler that the new type Person 38 is of type 'struct Person' so that when 37 it sees that inside the definition of struct 36 People it knows what it means.

In your particular 35 case, you could actually get away with only 34 predeclaring the People typdef because that 33 is the only type used before it is defined. By 32 the time you get into the definition of 31 struct People, you have already fully defined 30 the type Person. So the following would 29 also work but is NOT RECOMMENDED because it is fragile:

typedef struct People People;

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

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

If 28 you swap the order of the structure definitions 27 (moving struct People above the typedef 26 of Person) it will fail again. That's what 25 makes this fragile and, therefore, not recommended.

Note 24 that this trick does NOT work if you include 23 a struct of the specified type rather than 22 a pointer to it. So, for example, the following 21 WILL NOT compile:

typedef struct Bar Bar;

struct Foo
{
    Bar bar;
};

struct Bar
{
    int i;
};

The above code gives a compiler error because 20 the type Bar is incomplete when it tries 19 to use it inside the definition of struct 18 Foo. In other words, it doesn't know how 17 much space to allocate to structure member 16 'bar' because it hasn't seen the definition 15 of struct bar at that point.

This code will compile:

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;
};

This 14 works, even with the circular pointers inside 13 Foo and Bar, because the types 'Foo' and 12 'Bar' have been pre-declared (but not yet 11 defined) so the compiler can build a pointer 10 to them.

By the time we get to defining FooBar, we 9 have defined how big both Foo and Bar are 8 so we can include the actual objects there. We 7 can also include a self-referential pointer 6 to type FooBar because we have pre-declared 5 the type.

Note that if you moved the definition 4 of struct FooBar above the definitions of 3 either struct Foo or Bar, it would not compile 2 for the same reason as the previous example 1 (incomplete type).

Score: 34

Forward-declare one of the structs:


struct people;

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

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

0

Score: 6

As for readability :

typedef struct Foo_ Foo;
typedef struct Bar_ Bar;

struct Foo_ {
    Bar *bar;
};

struct Bar_ {
    Foo *foo;
};

It might be a good idea 1 to avoid typedef struct altogether;

Score: 2

Since Person just wants a pointer to People, it should 3 be fine to just predeclare the latter:

typedef struct People People;

Then 2 change the second declaration to just declare 1 using the struct tag, like so:

struct People {
    int count;
    int max;
    Person data[];
};
Score: 1
struct _People;

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

struct _People {
    int count;
    int max;
    Person data[1];
};

Note: Is Person data[]; standard?

0

Score: 0
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;

0

More Related questions