TYPEDEF
Язык С позволяет определять имена новых типов данных с помощью ключевого слова typedef. На самом деле здесь не создается новый тип данных, а определяется новое имя существующему типу. Он позволяет облегчить создание машинно-независимых программ. Единственное, что потребуется при переходе на другую платформу, — это изменить оператор typedef. Он также может помочь документировать код, позволяя назначать содержательные имена стандартным типам данных. Стандартный вид оператора typedef следующий:
typedef тип имя;
где тип — это любой существующий тип данных, а имя — это новое имя для данного типа. Новое имя определяется в дополнение к существующему имени типа, а не замещает его. Например, можно создать новое имя для float, используя
typedef float balance;
Данный оператор сообщает компилятору о необходимости распознавания balance как другого имени для float. Далее можно создать вещественную переменную, используя balance:
Здесь past_due — это вещественная переменная типа balance, другими словами — типа float. Можно использовать typedef для создания имен для более сложных типов. Например:
typedef struct float due;
int over_due;
char name[40];
> client; /* здесь client — это имя нового типа */
client clist[NUM_CLIENTS]; /* определение массива структур типа client */
Использование typedef может помочь при создании более легкого для чтения и более переносимого кода. Но надо помнить, что на самом деле не создаются никакие новые типы данных.
Переопределение типов
typedef широко применяются в Windows API для описания типов функций, применяемых в программировании оконных приложений Windows.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include
#include
typedef struct Books
char title[50], author[50], subject[100];
int book_id;
> Book;
int main() Book book;
strcpy_s(book.title, «C Programming» );
strcpy_s(book.author, «Nuha Ali» );
strcpy_s(book.subject, «C Programming Tutorial» );
book.book_id = 6495407;
printf( «book title : %s\n» , book.title);
printf( «book author : %s\n» , book.author);
printf( «book subject : %s\n» , book.subject);
printf( «book book_id : %d\n» , book.book_id);
getchar(); getchar();
return 0;
>

Результат выполнения:
Комментариев к записи: 3
как-то совсем поверхностно. Тут читаешь всё так просто — тип потом его «псевдоним» и всего делов.. А когда смотришь какие-нибудь официальные примеры там — typedef HRESULT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT*) и начинает казаться что автор как-то сильно что-то не договаривает об этом операторе.. ну или сам не знает..
typedef — КРАТКИЙ ОБЗОР
Функция typedef позволяет нам создать свое собственное имя типа. Это напоминает директиву #define, но со следующими тремя изменениями:
1. В отличие от #define функция typedef дает символические имена, но ограничивается только типами данных.
2. Функция typedef выполняется компилятором, а не препроцессором.
3. В своих пределах функция typedef более гибка, чем #define.
Посмотрим, как она работает. Предположим, вы хотите использовать термин real для чисел типа float. Тогда вы определяете термин real, как если бы он был переменной типа float, и перед его определением ставите ключевое слово typedef:
typedef float real;
С этого момента вы можете использовать real для определения переменных:
Область действия такого определения зависит от расположения оператора typedef. Если определение находится внутри функции, то область действия локальна и ограничена этой функцией. Если определение расположено вне функции, то область действия глобальна.
Часто в этих определениях используются прописные буквы, чтобы напомнить пользователю, что имя типа является на самом деле символической аббревиатурой:
typedef float REAL;
В последнем примере можно было бы применить директиву #define. А здесь это делать нельзя:
typedef char *STRING;
Без ключевого слова typedef оператор определял бы STRING как указатель на тип char. С ключевым словом оператор делает STRING идентификатором указателей на тип char. Так,
STRING name, sign;
Мы можем использовать typedef и для структур. Вот пример:
typedef struct COMPLEX
Кроме того, можно использовать тип COMPLEX для представления комплексных чисел.
Одна из причин использования typedef заключается в создании удобных, распознаваемых имен для часто встречающихся типов. Например, многие пользователи предпочитают применять STRING или его эквивалент, как это мы делали выше. Вторая причина: имена typedef часто используются для сложных типов. Например, описание
typedef char *FRPTC ( ) [5];
приводит к тому, что FRPTC объявляет тип, являющийся функцией, которая возвращает указатель на пятиэлементный массив типа char. (См. «Причудливые описания».)
Третья причина использования typedef заключается в том, чтобы сделать программы более мобильными. Предположим, например, что вашей программе нужно использовать 16-разрядные числа. В некоторых системах это был бы тип short, в других же он может быть типом int. Если вы использовали в ваших описаниях short или int, то должны изменить все описания, когда перейдете от одной системы к другой. Вместо этого сделайте следующее, В файле директивы #include есть такое определение:
typedef short TWOBYTE;
Используйте TWOBYTE в ваших программах для переменных типа short, которые должны быть 16-разрядными. Тогда если вы перемешаете программу туда, где необходимо использовать тип int, то следует только изменить одно определение в вашем файле директивы #include:
typedef int TWOBYTE;
Это пример того, что делает язык Си столь мобильным. При использовании typedеf следует иметь в виду, что он не создаст новых типов, он только создает удобные метки.
Читайте также
Краткий обзор технологий
Краткий обзор технологий При этом все основные методы можно разбить на 6 групп (каждая из которых позволяет решить одну из заявленных задач).Уменьшение размера объектов. Здесь фигурируют сжатие и методы оптимизации изображений, подробнее об этом можно прочитать во
3.1. Краткий обзор интерфейса
3.1. Краткий обзор интерфейса Опытный пользователь, не первый год работающий с операционной системой Windows ХР, при переходе на новую операционную систему Windows Vista может немного растеряться. Действительно, несмотря на то что ничего революционного и кардинально нового в
3.3 Краткий обзор интерфейса
3.3 Краткий обзор интерфейса Если вы работали с другими операционными системами, полагаю, вы легко разберётесь в интерфейсе Ubuntu. Подробное знакомство с ним мы проведём после установки, а пока обратите внимание на главное меню системы в левом верхнем углу: Рис. 3.6: Главное
Краткий обзор
Краткий обзор «Методология с большой буквы» — это название того, как организация многократно производит и поставляет программные системы: кого в ней нанимают на работу и зачем, чего ожидают люди от своих коллег, какие условности они соблюдают, начиная от размещения
Краткий обзор делегатов .NET
Краткий обзор делегатов .NET Напомним, что тип делегата .NET – это обеспечивающий типовую безопасность объектно-ориентированный указатель функции. Когда вы объявляете делегат .NET, компилятор C# отвечает на это созданием изолированного класса, полученного из System.MulticastDelegate
2.1. Краткий обзор архитектуры хранения данных в MySQL
2.1. Краткий обзор архитектуры хранения данных в MySQL Архитектура хранения данных в MySQL позволяет профессионалу базы данных выбирать специализированный тип памяти для специфической потребности прикладной программы. Сервер MySQL изолирует прикладного программиста и DBA от
Первый просмотр: краткий обзор
Первый просмотр: краткий обзор #include — включение другого файла.Эта строка указывает компилятору, что нужно включить информацию, содержащуюся в файле stdio.h.main() — имя функции РИС. 2.1. Структура программы, написанной на языке Си.Любая программа, написанная на языке Си,
Краткий обзор класса TList
Краткий обзор класса TList Класс TList хранит указатели в формате массива. Указатели могут быть любыми. Они могут указывать на записи, строки или объекты. Класс имеет специальные методы для вставки и удаления элементов, поиска элемента в списке, перестановки элементов и, в
2. Краткий обзор С++
2. Краткий обзор С++ Эту главу мы начнем с рассмотрения встроенного в язык С++ типа данных “массив”. Массив – это набор данных одного типа, например массив целых чисел или массив строк. Мы рассмотрим недостатки, присущие встроенному массиву, и напишем для его
12.1. Краткий обзор
12.1. Краткий обзор Реализация обобщенного алгоритма не зависит от типа контейнера, поэтому одна основанная на шаблонах реализация может работать со всеми контейнерами, а равно и со встроенным типом массива. Рассмотрим алгоритм find(). Если коллекция не отсортирована, то,
Краткий обзор представленных материалов
Краткий обзор представленных материалов Разработка программ зачастую напоминает священный ритуал, построенный на произнесении ряда обязательных магических заклинаний. Особенно это касается Windows приложений. Windows-заклинания позволяют вывести графическое окно,
5.1 Знакомство и Краткий Обзор
5.1 Знакомство и Краткий Обзор Предназначение понятия класса, которому посвящены эта и две последующие главы, состоит в том, чтобы предоставить программисту инструмент для создания новых типов, столь же удобных в обращении сколь и встроенные типы. В идеале тип оределяемый
Глава 10. Краткий обзор
Глава 10. Краткий обзор Мы будем опираться на симбиоз взаимодействующих между собой методик. Методик, некоторые из которых были забыты десятилетия назад как непрактичные и наивные.Вот исходные материалы, из которых нам предстоит построить новую дисциплину разработки
Typedef c что это
Что такое typedef, и чем он отличается от #define?
Часть 2. Для чего еще нужен typedef.
Итак, в первой части мы уже определились с тем, что такое typedef и чем он так похож и не похож на #define.
typedef вводит новое имя (синоним) для существующего типа. Но только этим все не ограничивается Чего такого еще может typedef, чего невозможно сделать с #define?
С помощью typedef может быть объявлен любой тип, включая типы функции или массива.
typedef double (* MATH)(); // MATH — новое имя типа, представляющее указатель на
//функцию, возвращающую значения типа double
MATH cos; // cos — это указатель на функцию, возвращающую значения типа double
Можно привести эквивалентное объявление — double (* cos)();
typedef char SIMB[40]; //SIMB — массив из сорока символов
SIMB person; //переменная person — тоже массив из сорока символов
Это эквивалентно объявлению — char person[40];
Помимо этого, имена типов могут использоваться еще и в списке формальных параметров (в объявлении функций), в операциях приведения типов и в операции sizeof.
typedef способен весьма облегчить нам жизнь. И не только нам.
typedef можно использовать, чтобы значительно упростить синтаксис сложных объявлений (воззаботимся же, братия, о тех бедных программистах, которые приИдут после нас). Используя typedef, можно сделать простым даже объявление стандартной функции set_new_handler:
typedef void (*new_handler)();
new_handler set_new_handler(new_handler);
Итак, new_handler — указатель на функцию, которая не имеет параметров и ничего не возвращает, и set_new_handler — функция, которая берет new_handler как параметр и возвращает в результате new_handler. Все выглядит очень просто. Если сделать это без typedef, тому, кто будет сопровождать потом этот код, будет лучше сразу застрелиться.
void (*set_new_handler(void (*)()))();
Это, по сути, то же самое. Но зато выглядит ужасно.
Давайте рассмотрим класс, используемый для осуществления связи по протоколу IP. Это может быть что-то, похожее на такое определение сокета:
typedef int AddressFamily;
typedef int SocketType;
typedef int Protocol;
class Socket
public:
Socket(AddressFamily family, SocketType type, Protocol protocol);
. . .
Мы видим определение трех typedef — AddressFamily, SocketType, и Protocol. Они идентифицируют три определяющие характеристики, необходимые для создания сокета связи (смотрим книги Стивенса по TCP/IP — пригодится). В этом контексте typedef использовался, чтобы определить три различных логических типа, хотя все они, в этом случае, один и тот же фактический тип — int. Такое использование typedef иногда называют «концептуальное определение типов».
Таким образом, конструктор Socket явно более понятен, чем если бы эти три параметра были бы определены просто, как int. Одно из преимуществ концептуального определения типов состоит в том, что они обеспечивают логически более понятное и простое определение классов.
Другое преимущество концептуального определения типов в том, что оно обеспечивает некоторую независимость от платформы. Посмотрим на стандартные типы size_t и ptrdiff_t, которые обычно определяются так:
typedef unsigned int size_t;
typedef int ptrdiff_t;
Когда тип ptrdiff_t встречается в коде, сразу становится понятно, что кое-кто здесь собирается оценить разницу между указателями. Если же тип был бы просто int, скорее всего сначала подумалось бы об арифметике или операциях индексации, которые более обычны для простого int. Точно так же и size_t склоняет думать о размерности (количестве байтов), а не о некой произвольной целочисленной мере. Однако, это еще не все. int (или unsigned int) могут и не быть типом, соответствующим для представления этих величин на данной платформе (ну, не хватит их размерности). В конкретной реализации эти типы могут быть переопределены, чтобы они соответствовали поддерживаемым (реализацией) платформам. И тогда не будет никакой необходимости менять что-либо в пользовательском коде — независимость.
Одной из возможных ошибок, связанных с применением typedef, может стать ошибка с перегрузкой функций. Напомним, что сигнатуры перегруженных функций должны отличаться, как минимум, типом параметра или количеством параметров. Но списки параметров могут быть одинаковыми, несмотря на то, что выглядят абсолютно разными.
struct Phone <. >;
struct Record <. >;
typedef Phone Tel_no;
Record lookup(const Phone&);
Record lookup(const Telno&); // Telno и Phone это тот же самый тип
Выглядит, как вполне разные типы. А на самом деле — одно и тоже, ведь Telno — не новый тип, а всего лишь синоним типа Phone.
Между прочим, и C и C++ поддерживают повторные определения того же самого typedef, пока все определения идентичны. Однако, это не самая лучшая идея — переопределять любой typedef, и лучше, конечно, так не делать. Должна быть единственная точка определения, обычно в пределах общедоступного инклуд-файла, вместо того, чтобы иметь кучу независимых определений, которые могут вести к очень неприятным побочным эффектам. Особенно, если отличающиеся определения происходят в отдельно компилируемых модулях, которые линкуются совместно, особенно когда линковка динамическая.
На этом и завершим рассмотрение typedef.
Оговорюсь сразу, осталось еще множество моментов, не показанных в этой статье. Взять хотя бы вопрос применения typedef для контекстного определения типов. Но, мне кажется, эти вопросы уже выходят за рамки рассмотрения «для начинающих». Оставим их на самостоятельное изучение.
Или для отдельной статьи.
Если у вас возникает потребность подробного рассмотрения какого-либо вопроса по С++, пишите нам, мы попытаемся вам помочь.
Сергей Малышев (aka Михалыч).