|
|
|
|
|
# Псевдонимы для структурных типов
|
|
|
|
|
|
Название типа структуры всегда включает в себя ключевое слово struct. Язык позволяет вам создать для него псевдоним с тем же, или другим именем:
|
|
|
|
|
|
```c
|
|
|
struct triangle {
|
|
|
struct point points[3];
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
Позволяет не писать слово struct
|
|
|
НО МОЖЕТ ОЧЕНЬ СИЛЬНО ЗАПУТАТЬ КОД
|
|
|
НЕ делайте так
|
|
|
*/
|
|
|
typedef struct triangle triangle;
|
|
|
```
|
|
|
|
|
|
Язык C всё-таки очень низкоуровневый и в нём практически невозможно полностью абстрагироваться от управления памятью. В реальной программе нам, как правило, хочется знать, является тип структурным или каким-то ещё, и ключевое слово `struct` в имени типа помогает, несмотря на свою тяжеловесность. Например, Greg Kroah-Hartman, один из главных разработчиков ядра Linux, [считает](https://www.linuxjournal.com/article/5780), что `typedef` вводит разработчиков в заблуждение относительно размеров структур (особенно если речь идёт о структурах с большим количеством вложений); как следствие, разработчики копируют большие структуры не осознавая накладных расходов на это.
|
|
|
|
|
|
```c
|
|
|
struct point { double coord[3]; }
|
|
|
|
|
|
struct polytope {
|
|
|
struct point points[1000000];
|
|
|
};
|
|
|
typedef struct polytope;
|
|
|
|
|
|
...
|
|
|
polytope p1;
|
|
|
get_polytope( &p1 );
|
|
|
|
|
|
// Одно это присваивание означает копирование
|
|
|
// 24 мегабайт в памяти (а если p2 локальная переменная,
|
|
|
// то, скорее всего, стек уже переполнится)
|
|
|
polytope p2 = p1;
|
|
|
```
|
|
|
|
|
|
Исключениями, когда `typedef` со структурными типами делать можно, будут такие ситуации:
|
|
|
|
|
|
- создание структуры-обёртки над существующим типом.
|
|
|
|
|
|
```c
|
|
|
typedef struct {
|
|
|
char* addr;
|
|
|
} heap_string;
|
|
|
// heap_string это псевдоним для анонимного структурного типа struct { char* addr }
|
|
|
// так мы не создаём структурного типа с именем и можем использовать heap_string без ключевого слова struct
|
|
|
// Здесь struct используется как хак для создания псевдонима типа без добавления неявных конверсий
|
|
|
// и никак не означает, что внутри неё -- большая структура данных.
|
|
|
|
|
|
void print_and_deallocate( heap_string s ) {
|
|
|
printf(s.addr);
|
|
|
free( s.addr );
|
|
|
}
|
|
|
```
|
|
|
|
|
|
- структура намеренно делается [непрозрачным типом](opaque type), и мы осознанно не хотим никак с ней взаимодействовать, кроме как через выделенный набор функций. |
|
|
\ No newline at end of file |