Подтвердить что ты не робот

Решить круговую зависимость typedef?

Каков наилучший способ разрешить следующую циклическую зависимость при типизации этих структур?
Обратите внимание на тег языка C - я ищу решение в стандартном gcc C.

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

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

Ответ 1

Переслать-объявить одну из структур:


struct people;

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

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

Ответ 2

Ответ заключается в различии между декларацией и определением. Вы пытаетесь объявить и определить на том же шаге (в случае нового типа через 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;
};

Обратите внимание на добавление двух "пустых" typedefs в верхней части (декларации). Это говорит компилятору, что новый тип Person имеет тип "struct Person", поэтому, когда он видит, что внутри определения struct People он знает, что это значит.

В вашем конкретном случае вы действительно можете уйти с только предваряем People typdef, потому что это единственный тип, используемый до его определения. Когда вы войдете в определение структуры 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;
};

Если вы меняете порядок определений структуры (перемещая структуру "Люди" над типом "Личность" ), он снова не сработает. Это делает этот хрупкий и, следовательно, не рекомендуется.

Обратите внимание, что этот трюк НЕ работает, если вы включите структуру указанного типа, а не указатель на него. Например, следующий НЕ компилируется:

typedef struct Bar Bar;

struct Foo
{
    Bar bar;
};

struct Bar
{
    int i;
};

Приведенный выше код дает ошибку компилятора, потому что тип Bar является неполным, когда он пытается использовать его в определении struct Foo. Другими словами, он не знает, сколько места выделяется для элемента-элемента структуры, потому что он не видел определения строки структуры в этой точке.

Этот код будет компилировать:

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, поэтому мы можем включать в себя фактические объекты. Мы также можем включить self-referential указатель на тип FooBar, потому что мы предварительно объявили тип.

Обратите внимание, что если вы переместили определение структуры FooBar над определениями любой структуры Foo или Bar, оно не будет компилироваться по той же причине, что и предыдущий пример (неполный тип).

Ответ 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[];?

Ответ 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;