Разница между «struct» и «typedef struct» в C ++?

$ gcc -Wconversion test.c

test.c: In function ‘main’:
test.c:3: warning: conversion to ‘int’ from ‘double’ may alter its value
776
задан criddell 4 March 2009 в 20:41
поделиться

5 ответов

В C++ существует только тонкое различие. Это - пережиток от C, в котором это имеет значение.

стандарт языка C ( C89 В§3.1.2.3, C99 В§6.2.3, и C11 В§6.2.3) передает под мандат отдельные пространства имен для различных категорий идентификаторов, включая [1 128] идентификаторы тега (для 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 для него. Таким образом, с этой конструкцией, это не имеет имени в пространстве имен тега, только имени в пространстве имен определения типа. Это означает, что также не может быть вперед - объявлено. , Если Вы хотите сделать предописание, необходимо дать ему имя в пространстве имен .

тега <час>

В C++, весь struct / union / enum / class действие объявлений как, они неявно typedef 'редактор, пока имя не скрыто другим объявлением с тем же именем. См. ответ Michael Burr для полного изложения.

1133
ответ дан YePhIcK 5 March 2009 в 06:41
поделиться

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

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

62
ответ дан Michael Burr 5 March 2009 в 06:41
поделиться

В эта статья DDJ, Dan Saks объясняет одну небольшую площадь, где ошибки могут вползти через, если Вы не делаете определения типа Ваши структуры (и классы!):

, Если Вы хотите, можно предположить, что C++ генерирует определение типа для каждого имени тега, такой как [1 114]

typedef class string string;

, К сожалению, это не совсем точно. Мне жаль, что это не было настолько просто, но это не. C++ не может генерировать такие определения типов для структур, объединений или перечислений, не начиная несовместимости с C.

, Например, предположите, что программа C объявляет и функцию и структуру, названную состоянием:

int status(); struct status;

Снова, это может быть плохой практикой, но это - C. В этой программе состояние (отдельно) относится к функции; состояние структуры относится к типу.

, Если бы C++ действительно автоматически генерировал определения типов для тегов, то при компиляции этой программы как C++ компилятор генерировал бы:

typedef struct status status;

, К сожалению, это имя типа конфликтовало бы с именем функции, и программа не скомпилирует. Вот почему C++ не может просто генерировать определение типа для каждого тега.

В C++, действие тегов точно так же, как имена определения типа, за исключением того, что программа может объявить объект, функцию или перечислитель с тем же именем и тем же объемом как тег. В этом случае объект, функция или имя перечислителя скрывают имя тега. Программа может относиться к имени тега только при помощи класса ключевого слова, структуры, объединения или перечисления (как соответствующая) перед именем тега. Имя типа, состоящее из одного из этих ключевых слов, сопровождаемых тегом, является elaborated-type-specifier. Например, состояние структуры и перечислимый месяц является elaborated-type-specifiers.

Таким образом, программа C, которая содержит обоих:

int status(); struct status;

ведет себя то же при компиляции как C++. Одно только состояние имени относится к функции. Программа может относиться к типу только при помощи elaborated-type-specifier состояния структуры.

Поэтому, как это позволяет ошибкам вползать в программы? Рассмотрите программу в Список 1 . Эта программа определяет нечто класса с конструктором по умолчанию и оператор преобразования, который преобразовывает объект нечто обуглить константу *. Выражение

p = foo();

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

cout << p << '\n';

должен отобразить нечто класса, но это не делает. Это отображает функциональное нечто.

Этот неожиданный результат происходит, потому что программа включает заголовок lib.h показанный в [1 110] Список 2 . Этот заголовок определяет функцию, также названную нечто. Нечто имени функции скрывает нечто имени класса, таким образом, ссылка на нечто в основном относится к функции, не классу. основной может относиться к классу только при помощи elaborated-type-specifier, как в [1 126]

p = class foo();

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

typedef class foo foo;

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

я не знаю ни о ком, кто на самом деле пишет эти определения типов как само собой разумеющееся. Требуется большая дисциплина. Начиная с падения ошибок, таких как та в [1 111] Список 1 является, вероятно, довольно маленьким, Вы многие никогда не сталкиваются с этой проблемой. Но если ошибка в Вашем программном обеспечении могла бы нанести телесные повреждения, то необходимо записать определения типов, неважно, как вряд ли ошибка.

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

220
ответ дан Michael Burr 5 March 2009 в 06:41
поделиться

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

struct Foo bar;
-3
ответ дан xian 5 March 2009 в 06:41
поделиться
  • 1
    Это требует, чтобы все подсписки были тем же размером? Что, если они не? – garsh0p 8 October 2010 в 17:06

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

7.1.3 спецификатор определения типа

1 [...]

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

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

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

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

31
ответ дан dirkgently 5 March 2009 в 06:41
поделиться
Другие вопросы по тегам:

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