Зачем использовать определение типа * после * определения структуры? - PullRequest
11 голосов
/ 30 июля 2010

Оба в этом стиле:

struct _something
{
   ...
};
typedef struct _something someting;

и этот стиль:

typedef struct _something
{
  ...
} something;

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

Один недостаток первого объявления заключается в том, что при использовании любой IDE автоматический переход к объявлению часто направляет вас к typedef struct _something someting; вместо непосредственного определения реального определения структуры.

Во втором методе вы попадаете непосредственно к определению структуры.

Есть ли причина, по которой можно использовать первый метод?
Код, над которым я работаю, полон этих ...
Это просто плохая / хорошая привычка от сопровождающих?

Ответы [ 6 ]

4 голосов
/ 30 июля 2010

Есть одно явное преимущество разделения typedef и объявления структуры, и это преимущество очевидно, если вы разделяете оба в разных файлах. Это позволяет для инкапсуляции данных.

Вы объявляете в заголовочном файле свой

typedef struct whatever typename;

Это объявление типа struct whatever, не зная, как оно реализовано. Теперь вы можете объявить функции, которые являются частью интерфейса, не раскрывая ничего из структуры структуры. Передача указателя на это typename - это все, что нужно.

В файле реализации вашего "класса" (я помещаю это в кавычки, поскольку мы говорим здесь исключительно в контексте C), вы делаете это:

#include "header.h"

struct whatever {
  ...
  ...
  /* can even contain references to `struct whatever` or even `typename` */
};

Преимущество этой инкапсуляции в том, что вы можете изменять внутреннюю структуру без необходимости перекомпиляции остальной части приложения. Может пригодиться, если вы работаете с динамическими библиотеками.

3 голосов
/ 30 июля 2010

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

Этот стиль отделяет определение типа (то есть не что делает typedef) из-за создания синонима typename (который равен , что делает typedef), и сохраняет строгое соответствие между именем типа и синонимом типа без недостатка использования одного и того же имени для обоих (чтоможет сбить с толку некоторых отладчиков, и в любом случае это боль для grep).

1 голос
/ 30 июля 2010

Если вы отделите две вещи (typedef от объявления структуры), вы сможете, при необходимости, иметь непрозрачных указателей .

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

Читайте также ответ @ tristopia.

1 голос
/ 30 июля 2010

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

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

Или, возможно, был выбран стиль кодирования, который был выбран прихотью, прежде чем стали доступны мощные IDE.

0 голосов
/ 30 июля 2010

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

0 голосов
/ 30 июля 2010

когда вы определяете структуру:

struct something
{
   ...
};

Вы создали новый тип, называемый «struct что-то».

Вы можете использовать это в своем приложении как:

struct something myvar;

Но большинству людей не нравится печатать struct (особенно с большим количеством указателей):

struct something *test = (struct something*)malloc(sizeof(struct something))

Поэтому вместо этого вы вводите определение по умолчанию (любым из описанных вами способов):

struct something
{
   ...
};
typedef struct _something someting;

или

typedef struct _something
{
  ...
} something;

Таким образом, когда вы используете структуру, вы можете сделать это:

something *test = (something*)malloc(sizeof(something))

Насколько вы ее определяете, не имеет значения.

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

...