netlib.narod.ru | < Назад | Оглавление | Далее > |
Язык Си предоставляет инструкцию typedef, которая позволяет давать типам данных новые имена. Например, объявление
typedef int Length;
делает имя Length синонимом int. С этого момента тип Length можно применять в объявлениях, в операции приведения типа и т.д. точно так же, как тип int:
Length len, maxlen; Length *lengths[];
Аналогично объявление
typedef char *String;
делает String синонимом char *, т.е. указателем на char, и правомерным будет, например, следующее его использование:
String p, lineptr[MAXLINES], alloc(int); int strcmp(String, String); p = (String)malloc(100);
Заметим, что объявляемый в typedef тип стоит на месте имени переменной в обычном объявлении, а не сразу за словом typedef. С точки зрения синтаксиса слово typedef напоминает класс памяти — extern, static и т.д. Имена типов записаны с заглавных букв для того, чтобы они выделялись в тексте программы.
Для демонстрации более сложных примеров применения typedef воспользуемся этим средством при задании узлов деревьев, с которыми мы уже встречались в данной главе.
typedef struct tnode *Treeptr; typedef struct tnode { /* узел дерева */ char *word; /* указатель на текст */ int count; /* число вхождений */ Treeptr left; /* левый потомок */ Treeptr right; /* правый потомок */ } Treenode;
В результате создаются два новых названия типов: Treenode (структура) и Treeptr (указатель на структуру). Теперь функцию talloc можно записать в следующем виде:
Treeptr talloc(void) { return (Treeptr)malloc(sizeof(Treenode)); }
Следует подчеркнуть, что объявление typedef не создает объявления нового типа, оно лишь дает новое имя уже существующему типу. Никакого нового смысла эти новые имена не несут, они объявляют переменные в точности с теми же свойствами, как если бы те были объявлены напрямую без переименования типа. Фактически typedef аналогичен #define с тем лишь отличием, что при интерпретации компилятором он может справиться с такой текстовой подстановкой, которая не может быть обработана препроцессором. Например
typedef int (*PFI)(char *, char *);
создает тип PFI — «указатель на функцию с двумя аргументами типа char *, возвращающую значение типа int», который например, в программе сортировки, описанной в главе 5, можно использовать в таком контексте:
PFI strcmp, numcmp;
Помимо просто эстетических соображений, для применения typedef существуют две важные причины. Первая — параметризация программы, связанная с проблемой переносимости. Если с помощью typedef объявить типы данных, которые являются машинно-зависимыми, то при переносе программы на другую машину потребуется внести изменения только в определения typedef. Одна из распространенных ситуаций — использование определенных через typedef имен для объявления целых величин. Для каждой конкретной машины это предполагает соответствующие установки short, int или long, которые делаются аналогично установкам стандартных типов, например size_t и ptrdiff_t.
Вторая причина, побуждающая к применению typedef, — желание сделать более ясным текст программы. Тип, названный Treeptr (от английских слов tree — дерево и pointer — указатель), более понятен, чем тот же тип, записанный как указатель на некоторую сложную структуру.
netlib.narod.ru | < Назад | Оглавление | Далее > |