Во-первых, оба объявления допустимы как на C, так и на C ++. Однако в Си они имеют немного другую семантику. (В частности, способ, которым вы ссылаетесь на структуру позже, меняется).
Ключевым понятием, которое нужно понять, является то, что в C структуры существуют в отдельном пространстве имен.
Все встроенные типы, а также определения типов существуют в пространстве имен «по умолчанию». То есть, когда я набираю int
, компилятор проверяет только это пространство имен «по умолчанию». Если я наберу «tagMyStruct», как в вашем примере, компилятор также проверяет только это одно пространство имен. Но в зависимости от того, какой тип объявления вы используете, структура может не существовать в этом пространстве имен.
Структуры разные и существуют в отдельном пространстве имен. Поэтому, если я сделаю следующее заявление:
struct mystruct {};
Я могу не просто называть это mystruct. Вместо этого я должен указать, что я хочу, чтобы mystruct существовал в пространстве имен struct:
void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter
Который становится немного многословным и неловким в долгосрочной перспективе. Вместо этого вы можете ввести его в пространство имен по умолчанию:
typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace
и теперь моя функция может быть объявлена простым способом:
void foo(mystruct bar);
Итак, ваш первый пример просто объединяет эти два шага: объявите структуру и поместите псевдоним в обычное пространство имен. И, конечно же, поскольку мы все равно определяем его, нам не нужно «оригинальное» имя, поэтому мы можем сделать структуру анонимной. Итак, после вашей декларации
typedef struct { int i; double d; } tagMyStruct;
у нас есть структура без имени, которая была определена с помощью typedef в tagMyStruct в пространстве имен по умолчанию.
Вот как С относится к этому. Оба типа объявлений являются допустимыми, но один не создает псевдоним в пространстве имен «по умолчанию», поэтому вы должны использовать ключевое слово struct каждый раз, когда ссылаетесь на тип.
В C ++ отдельное пространство имен struct не существует, поэтому они означают одно и то же. (но более короткая версия предпочтительна).
Редактировать Просто чтобы прояснить, нет, C не имеет пространств имен. Не в обычном смысле.
C просто помещает идентификаторы в одно из двух предопределенных пространств имен. Имена структур (и, как я помню, перечисления) помещаются в один, а все остальные идентификаторы - в другой. Технически, это пространства имен, потому что они являются отдельными «контейнерами», в которые помещаются имена, чтобы избежать конфликтов, но они определенно не являются пространствами имен в смысле C ++ / C #.