Typedef struct перед объявлением
Я не новичок, я очень хорошо знаком со следующей идиомой:
typedef struct Foo_ Foo;// I know typedef struct Foo Foo is fine, I'm just trying to make it clearer
struct Foo_
{
int value;
Foo *link;
};
Я просто внезапно чувствую смущение, потому что я понимаю, что ему не разрешено использовать имя (идентификатор) до его объявления. Но в объявлении typedef struct Foo_ Foo
идентификатор Foo_
еще не существует! Почему компилятор разрешает это? Кто-нибудь, пожалуйста, пролил бы свет на это, объясните мне, какое оправдание для такого синтаксиса?
Цитата из Википедии: целью typedef
является назначение альтернативных имен для СУЩЕСТВУЮЩИХ типов.
--- > 8 ---
Спасибо всем парням за столь полезную информацию.
Ответы
Ответ 1
Это совершенно нормально. Первое использование тега struct
, такого как ваш, является прямым объявлением типа struct
.
Остерегайтесь, если ваше использование _Foo
соответствует не. Идентификаторы с ведущим подчеркиванием и следующей заглавной буквой зарезервированы. Не делай этого. Подчеркивание подчеркивания будет в порядке.
Ответ 2
Это описано в 6.7.2.3p8:
6.7.2.3 Теги
Семантика
[...] 8 - Если спецификатор типа идентификатора структуры или объединения имеет место иначе, чем [определение структуры или объединения] или [структурно-профсоюзная декларация], и никакое другое объявление идентификатор в виде тега, то он объявляет неполную структуру или тип объединения и объявляет идентификатор как тег этого типа.
Спецификатор типа struct Foo
в typedef struct Foo Foo
не находится в определении (struct Foo {...};
) или декларации (struct Foo;
), поэтому он подпадает под 6.7.2.3p8.
Обратите внимание, что нет ничего особенного в typedef
; вы также можете, например, написать
struct A { struct Foo *p; };
и предыдущее определение или объявление не должны быть видимыми.
Однако в объявлении функции или определении:
void foo(struct Foo *p);
Если struct Foo
не объявляется ранее, то область объявления будет просто объявлением или определением функции, и она не будет совместима с типом любого последующего объявления или определения Foo
.
Ответ 3
ISO c99 : 6.2.1 Scopes of identifiers
7
Элементы структуры, объединения и перечисления имеют область, которая начинается сразу после появления
тег в спецификаторе типа, который объявляет тег.
typedef struct _Foo Foo; // You can do this because it just the typedef the new type
struct _Foo *myfoo ; // It pointer to struct _Foo (an incomplete type)
//but make sure before using myfoo->value
// struct definition should be available
struct _Foo MyFoo; // It definition of MyFoo but don't forget
// to give the definition of struct _Foo (gcc extension).
struct _Foo; // forward declaration
struct _Foo // It the definition
{
int value;
Foo *link;
};
Просто, как и для functions
, мы выполняем forward declaration
или typedef
до фактического определения функции. Поэтому мы также можем сделать это с помощью struct
.
void func(int );
typedef void (*func_t)(int);
void func(int x)
{
//actual definition
}
Ответ 4
typedef
используется для создания псевдонима для типа. Но этот тип не обязательно существует, когда typedef'ed.
Например,
если вы просто выполните:
struct Foo;
и вы никогда не определяете struct Foo
в любом месте программы, тогда он все равно будет компилироваться.
Компилятор предположил, что он определен где-то и продолжается. Только если вы используете его без определения структуры, произойдет ошибка.
Это аналогичный случай с typedef
.
Ответ 5
При определенных обстоятельствах допустимо использовать тип struct ...
до его объявления. Тогда это так называемый "неполный тип".
Например, допустимо объявить переменную как указатель на "неполную" структуру, а также (как вы можете видеть) a typedef
.
Ответ 6
Он вызвал вперед объявление. Объявление вперед позволяет использовать его имя в контексте, где разрешен неполный тип.
Компилятор "увидит" тэг typedef и сохранит его до тех пор, пока тип не будет найден, так как до тех пор, пока у вас есть тип, объявленный там после typedef, но перед любым использованием это прекрасно.
Ответ 7
Объявление typedef позволяет определять собственные идентификаторы, которые могут использоваться вместо спецификаторов типа, таких как int, float и double. Объявление typedef не резервирует хранилище.
для дополнительной информации http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc03typdef.htm