Используется ли typedef, потому что досадно добавлять «struct» в объявление структуры? [Дубликат]

добавить jquery ui плагин на вашей странице.

  function JsonDateFormate (dateFormate, jsonDateTime) {return $ .datepicker.formatDate (dateFormate, eval ('new' + jsonDateTime.slice (1,  -1)));  };   
681
задан criddell 4 March 2009 в 21:41
поделиться

7 ответов

В C ++ существует только тонкая разница.

Стандарт языка C ( C89 §3.1.2.3 , C99 §6.2.3 , и C11 §6.2.3 ) задает отдельные пространства имен для разных категорий идентификаторов, включая идентификаторы тегов (для struct / union / enum) и обычных идентификаторов (для typedef и других идентификаторов).

Если вы только что сказали:

struct Foo { ... };
Foo x;

, вы получите ошибку компилятора, потому что Foo определяется только в пространстве имен тегов.

Вы должны были бы объявить его как:

struct Foo x;

В любое время, когда вы хотите обратиться к Foo, вам всегда нужно называть его struct Foo , Это раздражает быстро, поэтому вы можете добавить typedef:

struct Foo { ... };
typedef struct Foo Foo;

Теперь struct Foo (в пространстве имен тегов) и просто Foo (в пространстве имен обычного идентификатора) оба относятся к то же самое, и вы можете свободно объявлять объекты типа Foo без ключевого слова struct.


Конструкция:

typedef struct Foo { ... } Foo;

является просто аббревиатурой для объявление и typedef.


Наконец,

typedef struct { ... } Foo;

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


В C ++ все struct / union / enum / class декларации действуют так, как будто они неявно typedef 'ed, если имя не скрыто другим объявлением с тем же именем. См. ответ Майкла Берра для полной информации.

1029
ответ дан YePhIcK 17 August 2018 в 13:40
поделиться
  • 1
    Хотя то, что вы говорите, истинно, AFAIK, утверждение, 'typedef struct {...} Foo;' создает псевдоним для неназванной структуры. – dirkgently 4 March 2009 в 21:51
  • 2
    Хорошая уловка, есть тонкая разница между "typedef struct Foo {...} Foo; & quot; и "typedef struct {...} Foo;". – Adam Rosenfield 4 March 2009 в 22:00
  • 3
    В C теги структуры, теги объединения и теги перечисления используют одно пространство имен, а не (struct и union), используя два, как указано выше; пространство имен, на которое ссылаются имена typedef, действительно является отдельным. Это означает, что вы не можете иметь «union x {...};» и 'struct x {...};' в одном объеме. – Jonathan Leffler 11 June 2009 в 05:28
  • 4
    Помимо не совсем типизированной вещи, другая разница между двумя частями кода в вопросе заключается в том, что Foo может определить конструктор в первом примере, но не во втором (поскольку анонимные классы не могут определять конструкторы или деструкторы) , – Steve Jessop 22 November 2009 в 03:45
  • 5
    @Lazer: Там есть тонкие различия, но Адам означает (как он говорит далее), что вы можете использовать «Тип var» для объявления переменных без typedef. – Fred Nurk 7 February 2011 в 21:49

Struct - создать тип данных. Typedef - установить псевдоним для типа данных.

-1
ответ дан David Tu 17 August 2018 в 13:40
поделиться

Есть разница, но тонкая. Посмотрите на это следующим образом: struct Foo вводит новый тип. Второй создает псевдоним Foo (а не новый тип) для неназванного типа struct.

7.1.3 Спецификатор typedef

1 [.. .]

Имя, объявленное с помощью спецификатора typedef, становится typedef-name. В пределах своей декларации имя typedef синтаксически эквивалентно ключевому слову и называет тип, связанный с идентификатором, способом, описанным в разделе 8. Таким образом, typedef-name является синонимом другого типа. Имя typedef не вводит новый тип , как это делает объявление класса (9.1) или объявление enum.

8 Если декларация typedef определяет неназванный класс (или перечисление) , первое имя typedef, объявленное объявлением как тип класса (или тип перечисления), используется для обозначения типа класса (или типа перечисления) только для целей привязки (3.5). [Пример:

typedef struct { } *ps, S; // S is the class name for linkage purposes

Итак, typedef всегда используется в качестве заполнителя / синонима для другого типа.

29
ответ дан dirkgently 17 August 2018 в 13:40
поделиться

Еще одно важное отличие: typedef s не может быть объявлено вперед. Таким образом, для опции typedef вы должны #include файла, содержащего typedef, что означает все, что #include s, ваш .h также включает этот файл, независимо от того, нуждается он в этом или нет, и так далее.

Без typedef в некоторых случаях вы можете просто добавить объявление вперед struct Foo; в верхней части вашего .h файла и только #include определение структуры в вашем файле .cpp.

205
ответ дан Michael Burr 17 August 2018 в 13:40
поделиться
  • 1
    В случае, если вы попробуете & quot; class foo () & quot; и он терпит неудачу: в ISO C ++ «class foo ()» является незаконной конструкцией (статья была написана '97, до стандартизации, кажется). Вы можете указать класс typedef foo foo; & quot; в основной, тогда вы можете сказать «foo (); & quot; (потому что тогда typedef-имя лексически ближе, чем имя функции). Синтаксически в T () T должен быть спецификатором простого типа. уточненные спецификаторы типов не допускаются. Конечно, это хороший ответ. – Johannes Schaub - litb 5 July 2009 в 22:36
  • 2
    Ссылки Listing 1 и Listing 2 нарушены. Взгляни. – Prasoon Saurav 13 October 2010 в 18:05
  • 3
    Почему подверженность определению структуры влияет на время сборки? Компилятор делает дополнительную проверку, даже если это не нужно (учитывая параметр typedef, чтобы компилятор знал определение), когда он видит что-то вроде Foo * nextFoo; ? – Rich 12 March 2014 в 19:21
  • 4
    Это не лишняя проверка, это просто больше кода, с которым компилятор должен справиться. Для каждого файла cpp, который встречает этот typedef где-то в своей цепочке include, его компиляция typedef. В больших проектах файл .h, содержащий typedef, может быть легко скомпилирован сотни раз, хотя предварительно скомпилированные заголовки помогают много. Если вам удастся использовать декларацию forward, то проще ограничить включение .h, содержащего полную спецификацию структуры, только коду, который действительно заботится, и поэтому соответствующий файл include скомпилируется реже. – Joe 12 March 2014 в 22:02
  • 5
    пожалуйста, @ предыдущий комментатор (кроме владельца сообщения). Я почти упустил ответ ур. Но спасибо за информацию. – Rich 13 March 2014 в 18:43
  • 6
    Это больше не относится к C11, где вы можете набирать одну и ту же структуру с одним и тем же именем несколько раз. – michaelmeyer 13 September 2015 в 16:13
  • 7
    Если вы используете разные соглашения об именах для классов и функций, вы также избегаете конфликта имен, не добавляя лишних typedef. – zstewart 9 May 2017 в 16:34

Важное различие между «typedef struct» и «struct» в C ++ заключается в том, что инициализация inline-члена в «typedef structs» не будет работать.

// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };
0
ответ дан user2796283 17 August 2018 в 13:40
поделиться
  • 1
    Не верно. В обоих случаях инициализируется x. См. тест в онлайн-среде ID Coliru (я инициализировал его до 42, чтобы он был более очевидным, чем с нулем, что назначение действительно имело место). – Colin D Bennett 29 July 2016 в 16:24
  • 2
    Фактически, я тестировал его в Visual Studio 2013, и он не был инициализирован. Это была проблема, с которой мы столкнулись в производственном коде. Все компиляторы разные и только должны соответствовать определенным критериям. – user2796283 30 July 2016 в 20:59

В C ++ нет разницы, но я верю в C, что позволит вам явно объявлять экземпляры структуры Foo:

struct Foo bar;
-2
ответ дан xian 17 August 2018 в 13:40
поделиться
  • 1
    Посмотрите на ответ @ dirkgently --- там есть разница, но она тонкая. – Keith Pinson 5 September 2012 в 18:51

Вы не можете использовать форвардное объявление с помощью typedef struct.

Сама структура является анонимным типом, поэтому у вас нет фактического имени для переадресации объявления.

typedef struct{
    int one;
    int two;
}myStruct;

Прямое объявление, подобное этому, не работает:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types
10
ответ дан Yochai Timmer 17 August 2018 в 13:40
поделиться
  • 1
    Я не получаю вторую ошибку для прототипа функции. Почему это говорит «переопределение»; различные базовые типы & quot ;? компилятору не нужно знать, как выглядит определение myStruct, правильно? Независимо от того, взяты ли с помощью фрагмента кода (typedef one или forward declaration one), myStruct обозначает тип структуры, правильно? – Rich 12 March 2014 в 19:30
  • 2
    @Rich Он жалуется, что существует конфликт имен. Есть декларация, в которой говорится «искать структуру, называемую myStruct». а затем есть typedef, который переименовывает безымянную структуру как «myStruct». – Yochai Timmer 13 March 2014 в 09:48
  • 3
    Вы имеете в виду как typedef, так и forward декларацию в том же файле? Я сделал, и gcc скомпилировал его в порядке. myStruct правильно интерпретируется как безымянная структура. Тег myStruct живет в пространстве имен тегов, а typedef_ed myStruct живет в обычном пространстве имен, в котором живут другие идентификаторы, такие как имя функции, имена локальных переменных. Поэтому конфликта не должно быть. Я могу показать вам свой код, если вы сомневаетесь любая ошибка в нем. – Rich 13 March 2014 в 10:07
  • 4
    @Rich GCC дает ту же ошибку, текст немного меняется: gcc.godbolt.org/… – Yochai Timmer 13 March 2014 в 10:15
  • 5
    Я думаю, что понимаю, что, когда вы имеете только typedef, декларацию вперед с именем typedef ed, не ссылаются на неназванную структуру. Вместо этого переднее объявление объявляет неполную структуру с тегом myStruct. Кроме того, не видя определения typedef, прототип функции с использованием имени typedef ed не является законным. Таким образом, мы должны включать весь typedef всякий раз, когда нам нужно использовать myStruct для обозначения типа. Исправьте меня, если я неправильно понял вас. Благодарю. – Rich 13 March 2014 в 10:23
Другие вопросы по тегам:

Похожие вопросы: