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

Почему "typedef struct foo foo;" считается вредным?

В typedef и struct namespaces в C vs С++, один из комментариев, по-видимому, подразумевает, что предоставление некоторого struct foo предпочтительнее использования typedef вдоль строк...

typedef struct foo foo;

... и затем используя foo вместо struct foo во всем API.

Есть ли недостатки в последнем варианте?

4b9b3361

Ответ 1

Это зависит от того, насколько вам нравится слово struct. Если вы чувствуете, что ваша программа станет более понятной из-за либерального разбрызгивания struct that и struct tother (конечно, у вас не может быть struct this в C++), тогда непременно используйте версию struct.

Лично я не думаю, что повторение struct дает какую-либо выгоду, и я счастлив использовать только имя typedef. И поскольку C++ эффективно предоставляет объявление typedef struct xyz xyz; автоматически (оно не совсем точное, не в последнюю очередь потому, что вы можете явно написать это в C++, но оно достаточно близко, чтобы вам, вероятно, не приходилось беспокоиться об этом), Я думаю, что имеет смысл использовать то же самое в C. Компилятор C доволен этим, поэтому я обычно использую typedef struct tag tag;, а затем использую tag и tag *, где это необходимо.


Для альтернативного, но вполне приемлемого представления, прочитайте руководство по стилю кодирования ядра Linux.


Обратите внимание, что C2011 позволяет вам переопределить typedef, если он имеет псевдоним того же типа:

ISO/IEC 9899: 2011 §6.7 Декларации

Semantics

¶5 Объявление определяет интерпретацию и атрибуты набора идентификаторов. Определение идентификатора - это объявление для этого идентификатора, которое:

- для объекта вызывает сохранение хранилища для этого объекта;

- для функции включает тело функции; 119)

- для константы перечисления является (единственным) объявлением идентификатора;

- для имени typedef - первое (или единственное) объявление идентификатора.

Сравните это с C99, где это было невозможно:

ISO/IEC 9899: 1999 §6.7 Декларации

Semantics

¶5 Объявление определяет интерпретацию и атрибуты набора идентификаторов. Определение идентификатора - это объявление для этого идентификатора, которое:

- для объекта вызывает сохранение хранилища для этого объекта;

- для функции включает тело функции; 98)

- для константы перечисления или имени typedef является (единственным) объявлением Идентификатор.

Это упрощает создание определений типов, если вы последовательны (но только если у вас есть достаточно совместимый компилятор C2011 на каждой платформе, имеющей отношение к вам).

Ответ 2

Единственный недостаток (*) заключается в том, что он скрывает тот факт, что foo является структурой, а не псевдонимом для некоторого встроенного типа.

Примечание (*): это вопрос вкуса, является ли это недостатком для вас.

  • Это полезно для полной непрозрачности (см. первый комментарий ниже).
  • Чтобы понять, почему некоторые люди считают это недостатком, проверьте стиль кодирования ядра Linux (глава typedefs).

Ответ 3

О том, есть ли типы структуры typedef:

Вот несколько мнений вокруг (все против структур типефинирования):

Из руководства по стилю OpenBSD:

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

Из стиля кодирования ядра Linux:

"Ошибочно использовать typedef для структур и указателей".

От Expert C Программирование Питера Ван дер Линдена:

"Не беспокойтесь о typedefs для structs. Все, что они делают, это сохранить ваше слово" struct ", что является ключом, который вы, вероятно, не должны скрывать в любом случае".

Ответ 4

Это более или менее вопрос вкуса.

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

Также, объявляя имя типа, вы позволяете людям не набирать struct, если они не хотят.

Мой комментарий в другом вопросе ссылался на объявление типа указателя с тем же именем, что и тег struct:

typedef struct foo * foo;

Стилистически, это немного неприятно, потому что скрывает тот факт, что это указатель. Это скрывает тот факт, что это указатель; возможно, это хорошо в контексте этого вопроса, где это непрозрачный тип, определенный API, но, на мой взгляд, будет довольно грубым для непрозрачного типа. Он также нарушает совместимость с С++. На этом языке такое объявление недопустимо, поскольку struct foo вводит foo в текущее пространство имен, а не в отдельное пространство тегов, и предотвращает объявление любого другого типа с тем же именем в этом пространстве имен.

Ответ 5

Просто придерживайтесь соглашения об именах, и все будет в порядке.

typedef struct
{
  //...
}              t_mytype;
//...
t_mytype thing;

Таким образом вы узнаете, что это нестандартный тип. Что касается того, что он является структурой, просто используйте явные имена и не реально t_mytype