struct rect { double х; double у; }; int rect; // конфликт в С не возникает
Тем не менее, использование одного идентификатора двумя разными пугями может вызвать путаницу, к тому же это не разрешено в C++, т.к. там дескрипторы и переменные помещаются в то же самое пространство имен.
Структуры и другие формы данных 609
Средство typedef: краткое знакомство
Возможность typedef представляет собой усовершенствованное средство манипулирования данными, которое позволяет создавать собственное имя для типа. В этом отношении оно подобно директиве #define, но с гремя отличиями.
• В отличие от #define, средство typedef ограничено назначением символических имен только типам, но не значениям.
• Интерпретация typedef выполняется компилятором, а не препроцессором.
• В рамках своих ограничений средство typedef является более гибким, чем #def ine.
Давайте посмотрим, как работает typedef. Предположим, что вы хотите использовать элемент BYTE для обозначения однобайтовых чисел. Тогда вы просто объявляете BYTE, как если бы это была переменная типа char, и предваряете определение ключевым словом typedef:
typedef unsigned char BYTE;
После этого BYTE можно применять для определения переменных:
BYTE х, у[10] , * z;
Область видимости этого определения зависит от местоположения оператора typedef. Если определение находится внутри функции, область видимости будет локальной в пределах этой функции. Если определение находится вне функции, область видимости будет глобальной.
Для определений typedef часто используются прописные буквы, чтобы напоминать пользователю о том, что имя типа в действительности является символическим сокращением, но разрешены также и строчные буквы:
typedef unsigned char byte;
Имена в typedef подчиняются тем же правилам, которые регламентируют создание допустимых имен переменных.
Хотя создание имени для существующего типа может показаться незначительной возможностью, часто оно будет удобным. В предыдущем примере указание BYTE вместо unsigned char помогает документировать намерение применять переменные BYTE для представления чисел, а не символьных кодов. Использование typedef также способствует лучшей переносимости. Например, ранее мы упоминали о типе size_t, который представляет тип, возвращаемый операцией sizeof, и о типе time t, представляющем тип, который возвращается функцией time(). Стандарт С утверждает, что sizeof и time() возвращают целочисленные типы, но то, какими они должны быть, оставляет на усмотрение реализации. Причина отсутствия конкретики объясняется тем, что в комитете по стандартам С придерживаются мнения, что, скорее всего, не существует единого выбора, который был бы наилучщим для всех компьютерных платформ. Таким образом, было решено создать новое имя типа, подобное time t, и позволить реализациям применять typedef для установки этого имени в какой-то конкретный тип. Тогда появляется возможность предоставить общий прототип, такой как показанный ниже:
time_t time(time_t *);
В одной системе time_t может быть unsigned long, а в другой — unsigned long long. При условии, что включен заголовочный файл time.li, программа может получать доступ к подходящему определению, и в коде можно объявлять переменные типа
time t.
610 Глава 14
Некоторые возможности typedef можно продублировать с помощью #define. Например, указание
#define BYTE unsigned char
заставляет препроцессор заменять BYTE типом unsigned char. Ниже приведен пример typedef, который невозможно воспроизвести посредством #define:
typedef char * STRING;
Без ключевого слова typedef в этом примере сама переменная STRING идентифицировалась бы как указатель на char. Наличие typedef делает STRING идентификатором для указателей на char. Таким образом,
STRING name, sign; означает
char * name, * sign;
Предположим, что вместо этого вы поступили так:
#define STRING char *
Тогда
STRING name, sign; транслируется в
char * name, sign;
В этом случае указателем будет только name.
Средство typedef можно также использовать со структурами:
typedef struct complex { float real; float imag;
} COMPLEX;
Теперь для представления комплексных чисел вместо структуры по имени complex можно применять тип COMPLEX. Одна из целей использования typedef связана с созданием удобных и легко опознаваемых имен для часто встречающихся типов. Например, многие программисты предпочитают применять имя типа STRING или его эквивалент, как в ранее показанном примере. При использовании typedef для именования типа структуры дескриптор можно не указывать:
typedef struct {double х; double у,() rect;
Предположим, что определенный посредством typedef идентификатор применяется так, как показано ниже:
Читать дальше