Использование анонимной структуры против именованной структуры с typedef - PullRequest
0 голосов
/ 18 февраля 2019

Когда следует использовать одно из следующих утверждений над другим?

typedef struct Foo {
    int a;
} Bar;

и

typedef struct {
    int a;
} Bar;

и использовать его как

Bar bar1 = { 5 };

Я понимаювторая - анонимная структура, но она не уверена, когда следует использовать одну поверх другой.

Ответы [ 6 ]

0 голосов
/ 18 февраля 2019

Многие другие люди сосредотачиваются на самореференциальном аспекте этого, но другая причина, чтобы избежать этого, состоит в том, что из-за отсутствия пространства имен в C. В некоторых кругах это стандартная практика, чтобы не typedef структуры избегают struct квалификатор и вместо этого ссылаются на структуры с полным спецификатором (например, void foo(struct Foo* foo_ptr)).Поэтому, если вы хотите сохранить такой стиль, у вас не будет возможности злоупотреблять анонимными структурами, поэтому это:

typedef struct {
  int a;
} Bar;

Bar bar1 = {5};

всегда вместо этого должно быть

struct Bar{
  int a;
};

struct Bar bar1 = {5};

, иначе вы не сможетедаже не скомпилировать инстанцирование bar1 без typedef исключения struct квалификатора

0 голосов
/ 18 февраля 2019

При создании непрозрачного типа данных, когда заголовок содержит только прямое объявление struct и фактическое определение его членов находится в исходном файле.Поскольку вы не можете переслать декларацию typedef, вам придется дать struct имя.Пример:

Foo.h

typedef struct Foo_ Foo;

Foo.c

struct Foo_ {
    int a;
};

Также, когда у вас есть рекурсивная структура данных, такая как связанный список, который упоминали все остальные.

0 голосов
/ 18 февраля 2019

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

Одна из ситуаций, когда вы хотите использовать неанонимное имя, - это когда вам нужны указатели на объект того же типа, как в связанном списке.

typedef struct Node {
    struct Node* next;
    int data;
} Node;

Одна альтернатива:

typedef struct Node Node;

struct Node {
    Node * next;
    int data;
};

Согласно Линусу Торвальдсу, вам следует избегать структур определения типа, если вы не хотите их скрывать.Из Руководства по стилю кодирования ядра Linux :

Пожалуйста, не используйте такие вещи, как vps_t.Ошибочно использовать typedef для структур и указателей.Когда вы видите vps_t a; в источнике, что это значит?Напротив, если он говорит struct virtual_container *a;, вы можете сказать, что это такое.

Многие думают, что typedefs помогают читабельности.Не так.Они полезны только для:

a) полностью непрозрачных объектов (где typedef активно используется, чтобы скрыть, что это за объект).

...

В соответствии с этим, вы никогда не должны использовать анонимные структуры, а typedefs предназначены исключительно для интерфейсов.Таким образом, это должно выглядеть так:

typedef struct Node {
    struct Node* next;
    int data;
} Node;

Но если вы действительно создаете интерфейс, вы должны разделить его на файл заголовка и исходный файл.В этом случае поместите typedef в заголовочный файл и НЕ используйте typedef: ed type вообще в исходном файле.

.c

struct Node {
    struct Node* next;
    int data;
} Node;

void insert(struct Node* head, int data) 
{
// Code
}    

.h

typedef struct Node Node;

void insert(Node* head, int data);

Принимая во внимание все вышесказанное, единственная допустимая ситуация для использования анонимной структуры - это если вы объявляете объект в одно и то же время, как это:

struct {
    int data;
    float more_data;
} myObject; 
0 голосов
/ 18 февраля 2019

Термин анонимная структура уже используется для чего-то другого: во вложенных структурах (или объединениях), которые вообще не имеют имени и чьи поля называются записями в родительском элементе..

Фактический вопрос о том, когда использовать одну или другую, заключается в том, что вам нужно использовать первую форму, если вы хотите добавить указатель на ее собственный тип внутри нее, например:

typedef struct Foo { struct Foo* Child; ... } Foo;

Тем не менее, я бы предпочел сделать это с помощью typedef примерно так:

typedef struct Foo Foo;
struct Foo {Foo* Child;};
0 голосов
/ 18 февраля 2019

Первый случай необходим, если вы создаете связанный список:

typedef struct list {
    int data;
    struct list *next;
} list;

typedef list не отображается внутри определения структуры, поэтому вам нужно использовать фактическийимя структуры для создания указателя на нее.

Если у вас нет такой структуры, вы можете использовать любую из них.

Однако не следует использовать имя тега, котороеначинается с подчеркивания, то есть:

typedef struct _list {
    int data;
    struct list *next;
} list;

Поскольку имена, начинающиеся с подчеркивания, зарезервированы реализацией.

0 голосов
/ 18 февраля 2019

Это не имеет большого значения.Если вы используете помеченную форму, вы можете иметь указатели на struct Foo внутри struct Foo (AKA Bar)

typedef struct Foo{
  int a;
  struct Foo *foop;
} Bar;

, но это невозможно сделать со второй формой

typedef struct {
  int a;
  //Baz *p; not valid here since Baz isn't a typename yet
} Baz;

Некоторые кодовые базы предпочитают вообще не использовать typedef s и просто каждый раз произносить struct Foo с ключевым словом struct.

Кроме того, в первой форме вы можете ссылаться на тип либо через тег(struct Foo) или с typedefs (Bar или любым будущим / предыдущим typedef с (вы можете сделать typedef struct Foo PreviousTypedef; до того, как предоставите определение).

Со второй формой нас другой стороны, вы можете использовать только Baz typedef и возможные будущие typedef s (вы не можете пересылать- typedef структуру, так как она не имеет тега).

(Обратите внимание, что typedef на самом деле не определяет типы в C. Часть struct optional_tag { /*...*/ } делает. Скорее, typedef предоставляет псевдонимы типов (поэтому, возможно, он должен был называться typealias).)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...