#c #структуры #объявление #typedef
Наверно какие-то C-шные ухищрения. Навроде их классов. Вроде бы и объявление тут
уже есть. Может поэтому? Вот такая строка например (из OpenCV):
typedef struct CvFileStorage CvFileStorage;
Зачем же так писать? Не нашел никак, сходу, ответ на это. Когда-то (несколько лет
назад), помню что читал об этом. Тогда чистый C был в моде наверное, а сейчас такое
позабыто получается. Еще подобное видел в коде от Windows CE6 и др. Это запомнил:),
а для чего нужно не помню никак. Если еще какие-то доп. куски кода надо привести, то
скажите. Эта строка стоит перед структурой, которая у себя где-то в поле использует
тип из этого typedef-а. Но зачем так писать, а не просто объявить его? Спасибо.
Ответы
Ответ 1
Имеется по крайней мере две веские причины объявить этот typedef.
typedef struct CvFileStorage CvFileStorage;
Первая причина заключается в том, что в C программах вы должны указывать ключевые
слова struct или enum перед именем структуры или перечисления. Это выглядит обременительно
при вводе кода. Очень часто программисты забывают указать эти слова, что приводит к
появлению ошибки компиляции. Поэтому этот typedef упрощает жизнь программистам, позволяя
им не писать эти ключевые слова перед именем структуры или перечисления.
Вторая причина состоит в том, что имена структур и другие идентификаторы находятся
в различных пространствах имен. Поэтому одно и то же имя можно использовать для объявления
структуры и обычной переменной. Например, следующий фрагмент кода является корректным
struct CvFileStorage
{
//...
};
int CvFileStorage;
В этом фрагменте кода объявляется структура с именем CvFileStorage и переменная типа
int с тем же самым именем. Эти объявления не конфликтует друг с другом, так как, как
уже было написано, перед именем структуры обязательно должно следовать ключевое слово
struct .
В C вы можете записать, к примеру
struct CvFileStorage
{
int CvFileStorage;
} CvFileStorage;
Это объявление корректно, так как эти три совпадающих идентификаторs находятся в
различных пространствах имен.
Однако это может вводить в заблуждение читающих код, так как если программист по
ошибке опустит ключевое слово struct перед именем структуры, то может оказаться, что
код по-прежнему с точки зрения синтаксиса языка будет корректным, хотя на самом деле
имелась в виду структура, а не переменная с таким же именем.
Например, в данном выражении программист по невнимательности забыл указать ключевое
слово struct, и тем не менее получил корректное выражение, так как имеется переменная
с таким же именем
sizeof( CvFileStorage )
Чтобы избежать такой путаницы также целесообразно резервировать это имя без ключевого
слова struct для имени структуры, используя typedef..
В С++ ключевое слово struct можно опускать при обращении к структуре. Тогда возникает
вопрос: а как быть с тем, что в C можно объявлять переменную или функцию с таким же
имеенем как имя структуры?
Этот вопрос решается следующим образом: имя переменной или имя функции скрывает объявление
структуры с тем же самым именем. Поэтому при обращении к структуре надо указывать уточненное имя.
Например,
struct CvFileStorage
{
//...
};
void CvFileStorage();
В этом фрагменте кода объявление функции скрывает объявление одноименной структуры.
Поэтому если, например, вы хотите объявить объект этой структуры, то надо будет указывать
уточненное имя структуры.
struct CvFileStorage obj;
Или, например, можно написать такие объявления
struct CvFileStorage
{
//...
};
void CvFileStorage( struct CvFileStorage );
Эти имена не будут конфликтовать друг с другом, так как для структуры используется
ее уточненное имя.
Ответ 2
В с++ если нужно объявить переменную типа структуры, нужно просто написать имя типа
и переменную. В чистом си это не так. И нужно всегда писать struct. Это все потому,
что типы для структур и остальные типы как бы находятся в разных областях видимости.
Но так как программисты существа ленивые, то лучше один наз написать
typedef struct CvFileStorage CvFileStorage;
и потом не задумываться, почему оно не компилируется (потому что забыли struct) или
почему оно работает как то странно (потому что забыли struct, а кто то объявил свой
тип не структуру с таким же именем).
Но часто пишут ещё интереснее:
typedef struct {
// тут объявление структры
} struct_name;
В этом случае создается сразу все так, как привычно в обычном с++.
Ответ 3
Без этого typedef при любом упоминании структуры CvFileStorage надо писать полностью:
struct CvFileStorage cv;
void func(struct CvFileStorage* cv);
и так далее. При наличии объявления typedef слово struct можно выбрасывать:
CvFileStorage cv;
void func(CvFileStorage* cv);