netlib.narod.ru< Назад | Оглавление | Далее >

6.7. Инструкция typedef

Язык Си предоставляет инструкцию 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< Назад | Оглавление | Далее >

Сайт управляется системой uCoz