Зачем использовать typedef *после* определения структуры?

Оба этого стиля:

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

и этот стиль:

typedef struct _something
{
  ...
} something;

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

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

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

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


person Gui13    schedule 30.07.2010    source источник
comment
Вам не хватает подчеркивания в первом примере?   -  person Amarghosh    schedule 30.07.2010


Ответы (6)


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

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

person Justin Ethier    schedule 30.07.2010
comment
Амаргош исправил опечатку; имя структуры и имя синонима typedef различны (забыл подчеркивание). В остальном я понимаю вашу точку зрения, даже если лично я предпочитаю второй -- более короткий -- стиль. - person Gui13; 30.07.2010

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

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

typedef struct whatever typename;

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

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

#include "header.h"

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

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

person Patrick Schlüter    schedule 30.07.2010
comment
Да, я иногда его использую, но в данном конкретном случае мне нужно, чтобы внутренняя структура была доступна из других частей программы. - person Gui13; 30.07.2010
comment
Вы можете сделать эту инкапсуляцию без typedef. Просто помещая предварительную декларацию, например. struct whatever; в заголовочном файле будет достаточно. - person Dan Moulding; 30.07.2010

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

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

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

person Darron    schedule 30.07.2010

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

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

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

person Andrei Ciobanu    schedule 30.07.2010
comment
Смотрите также мой ответ @tristopia =) - person Gui13; 30.07.2010

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

struct something
{
   ...
};

Вы создали новый тип под названием 'struct something'.

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

struct something myvar;

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

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

Поэтому вместо этого вы вводите его (в любом случае, как вы описали):

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

or

typedef struct _something
{
  ...
} something;

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

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

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

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

person Bob Fincheimer    schedule 30.07.2010
comment
«большинство людей не любят печатать». Это так. Есть идеи, почему? Ваш первый способ кажется мне самым нормальным и естественным. - person Brian Hooper; 30.07.2010

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

person binW    schedule 30.07.2010