Страницы

Поиск по вопросам

среда, 3 октября 2018 г.

Зачем typedef объвлять с одним и тем же типом

Наверно какие-то C-шные ухищрения. Навроде их классов. Вроде бы и объявление тут уже есть. Может поэтому? Вот такая строка например (из OpenCV):
typedef struct CvFileStorage CvFileStorage;
Зачем же так писать? Не нашел никак, сходу, ответ на это. Когда-то (несколько лет назад), помню что читал об этом. Тогда чистый C был в моде наверное, а сейчас такое позабыто получается. Еще подобное видел в коде от Windows CE6 и др. Это запомнил:), а для чего нужно не помню никак. Если еще какие-то доп. куски кода надо привести, то скажите. Эта строка стоит перед структурой, которая у себя где-то в поле использует тип из этого typedef-а. Но зачем так писать, а не просто объявить его? Спасибо.


Ответ

Имеется по крайней мере две веские причины объявить этот 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 );
Эти имена не будут конфликтовать друг с другом, так как для структуры используется ее уточненное имя.

Комментариев нет:

Отправить комментарий