
- •1.1 Перші кроки
- •1.2 Змінні й арифметичні вирази
- •1.3 Твердження for
- •1.4 Символічні константи
- •1.5 Ввід і вивід знаків
- •1.5.1 Копіювання файла
- •1.5.2 Відлік символів
- •1.5.3 Відлік рядків
- •1.6 Масиви
- •1.7 Функції
- •1.8 Аргументи - виклик за значенням
- •1.9 Символьні масиви
- •1.10 Зовнішні змінні й область дії
- •2.1 Назви змінних
- •2.2 Типи даних і розміри
- •2.3 Константи
- •2.4 Оголошення
- •2.5 Арифметичні операції
- •2.6 Реляційні та логічні оператори
- •2.7 Перетворення типів
- •2.8 Оператори приросту та спаду
- •2.9 Розрядні оператори
- •2.10 Оператори та вирази присвоєння
- •2.11 Вирази умов
- •2.12 Пріоритет і послідовність обчислення
- •3.1 Вирази та блоки
- •3.3 Else if
- •3.4 Switch
- •3.5 Цикли while та for
- •3.6 Цикли do-while
- •3.7 Break і continue
- •3.8 Goto та мітки
- •4.1 Основні знання про функції
- •4.2 Функції, які не повертають цілих
- •4.3 Зовнішні змінні
- •4.4 Правила області дії
- •4.5 Файли заголовка
- •4.6 Статичні змінні
- •4.7 Регістрові змінні
- •4.8 Структура блоків
- •4.10 Рекурсія
- •4.11 Препроцесор c
- •4.11.1 Включення файлів
- •4.11.2 Заміна макросів
- •4.11.3 Обумовлене включення файлів
- •5.1 Покажчики й адреси
- •5.2 Покажчики й аргументи функцій
- •5.3 Покажчики та масиви
- •5.4 Арифметика адрес
- •5.5 Покажчики на символи та функції
- •5.6 Масив покажчиків; покажчики на покажчики
- •5.7 Багатовимірні масиви
- •5.8 Ініціалізація масиву покажчиків
- •5.9 Покажчики в порівнянні з багатовимірними масивами
- •5.10 Аргументи командного рядка
- •5.11 Покажчики на функції
- •5.12 Складні оголошення
- •6.1 Основні поняття про структури
- •6.2 Структури та функції
- •6.3 Масиви структур
- •6.4 Покажчики на структури
- •6.5 Структури зі зворотнім звертанням
- •6.6 Пошук по таблиці
- •6.7 Typedef
- •6.8 Сполуки
- •6.9 Розрядні поля
- •7.1 Стандартний ввід і вивід
- •7.2 Форматований вивід - printf
- •7.3 Списки аргументів довільної довжини
- •7.4 Форматований ввід - scanf
- •7.5 Доступ до файлів
- •7.6 Обробка помилок - stderr і exit
- •7.7 Ввід і вивід рядків
- •7.8 Додаткові функції
- •7.8.1 Операції з ланцюжками
- •7.8.2 Перевірка і перетворення класів символів
- •7.8.3 Ungetc
- •7.8.4 Виконання команд
- •7.8.5 Керування пам'яттю
- •7.8.6 Математичні функції
- •7.8.7 Генератор випадкових чисел
- •8.1 Дескриптори файлів
- •8.2 Низькорівневий ввід/вивід - read і write
- •8.3 Open, creat, close, unlink
- •8.4 Довільний доступ - lseek
- •8.5 Приклад: втілення fopen і getc
- •8.6 Приклад - перелік вмісту каталогів
- •8.7 Приклад - розподільник пам'яті
6.7 Typedef
C передбачає засіб, що має назву typedef, який дозволяє створювати нові назви типів даних. Так, наприклад, оголошення
typedef int Length;
зробить назву Length синонімом int. Тепер тип Lengh можна вживати в оголошеннях, зведеннях тощо, так само як ми це робимо з int:
Length len, maxlen;
Length *lengths[];
Подібно до цього, оголошення
typedef char *String;
перетворить String у синонім 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 { /* the tree node: */
char *word; /* points to the text */
int count; /* number of occurrences */
struct tnode *left; /* left child */
struct tnode *right; /* right child */
} Treenode;
Це утворить дві нові назви типів із назвою Treenode (структура) і Treeptr (покажчик на структуру). Після цього, функція talloc виглядатиме як
Treeptr talloc(void)
{
return (Treeptr) malloc(sizeof(Treenode));
}
Слід однак підкреслити, що оголошення typedef не створює, власно кажучи, цілком нового типу — воно просто додає нову назву для того, який вже існує. Також, семантика не зазнає жодних змін — змінні, оголошені в такий спосіб, матимуть ті самі властивості, що й змінні, чий тип вказано безпосередньо. Фактично, typedef аналогічний #define за винятком того, що, через те, що його інтерпретовано компілятором, він може впоратися з текстовими замінами, які значно перевищують можливості препроцесора. Наприклад,
typedef int (*PFI)(char *, char *);
утворює тип PFI, який є покажчиком на функцію (з двома аргументами char *), і повертає ціле. Це можна використати в такому контексті, як
PFI strcmp, numcmp;
скажімо, програми sort з Розділу 5.
Попри чисто естетичні міркування, існують дві вагоміші причини використання typedef. Перша, це параметризувати програму від проблем з портабельністю. При використанні typedef з типами даних, які можуть виявитись машинозалежними, потрібно тільки поміняти typedef, коли програму перенесено на іншу машину. Поширеним випадком є використання typedef-назв для різноманітних цілих величин, після чого встановлення відповідних значень для short, int таlong для кожної окремої машини. Типи на зразок size_t та ptrdiff_t зі стандартної бібліотеки являються хорошим прикладом.
Другою ціллю typedef є надання кращої документації програмі - тип із назвою Treeptr легше зрозуміти ніж такий, що оголошено просто як покажчик на складну структуру.