Чтение онлайн

ЖАНРЫ

Программирование на Objective-C 2.0
Шрифт:

Чтобы определить имя нового типа с помощью typedef, нужно выполнить следующую процедуру.

Написать такое же объявление, как при объявлении переменной нужного типа.

Там, где должно быть имя объявляемой переменной, поместить имя нового типа.

Перед всем этим поставить слово typedef.

Для примера определим тип с именем Direction (Направление) как перечислимый тип данных со значениями east, west, north и south (восток, запад, юг и север), напишем определение этого перечислимого типа данных и подставим имя Direction там, где обычно ставится имя переменной. Перед всем этим нужно поместить ключевое слово typedef. typedef enum { east, west, south, north } Direction; После этого можно объявлять

переменные с типом Direction: Direction stepl, step2; Foundation framework содерж ит следую щ ее определение typedef для NSComparisonResult в одном из заголовочных файлов. enum NSComparisonResult { NSOrderedAscending = -1, NSOrderedSame, NSOrderedDescending }; typedef NSInteger NSComparisonResult;

Некоторые методы в Foundation framework, которые выполняют сравнение (comparison), возвращают значение этого типа. Например, метод сравнения строк Foundation с именем compare: возвращает значение типа NSComparisonResult после сравнения двух строк, которые являются объектами NSString. Этот метод объявляется следующим образом. -(NSComparisonResult) compare: (NSString *) string;

Чтобы проверить равенство двух объектов NSString с именами userName и savedName, можно включить в программу следующую строку. if ( [userName compare: savedName] == NSOrderedSame) { // Имена совпадают }

На самом деле здесь проверяется, равен ли нулю результат метода compare: 10.6. Преобразования типов данных

В главе 4 говорилось о том, что иногда при оценке выражений система неявным образом выполняет преобразования. Там рассматривался случай с типами данных float и int. Операция, включающая типы float и int, выполнялась как операция с плавающей точкой, и элемент данных целого типа автоматически преобразовывался в элемент с плавающей точкой.

Там же было показано, как использовать оператор приведения типа, чтобы явно определить преобразование. Пусть total и п являются целыми переменными. В строке average = (float) total / n;

значение переменной total преобразуется в тип float до выполнения операции, что гарантирует выполнение деления как операции с плавающей точкой. Правила преобразования

Компилятор Objective-C соблюдает строгие правила при оценке выражений, состоящих из разл ичных типов данных.

Ниже описывается порядок, в котором выполняются преобразования при оценке двух операндов в выражении.

Если один из операндов имеет тип long double, второй операнд преобразуется в long double, результат имеет такой же тип.

Если один из операндов имеет тип double, второй операнд преобразуется в double, результат имеет такой же тип.

Если один из операндов имеет тип float, второй операнд преобразуется в тип float, результат имеет такой же тип.

Если один из операндов имеет тип Bool, char, short int или bit field1 или перечислимый тип данных, то он преобразуется в тип int.

Если один из операндов имеет тип long long int, второй операнд преобразуется в long long int, результат имеет такой же тип.

Если один из операндов имеет тип long int, второй операнд преобразуется в long int, результат имеет такой же тип.

Если мы дошли до этого шага, то оба операнда имеют тип int, результат имеет такой же тип.

Это упрощенная версия шагов преобразования операндов в выражении. Правила усложняются, если включены операнды без знака (unsigned). Полный список правил см. в Приложении В.

Из этой последовательности шагов понятно, что если достигнут шаг, где говорится «результат имеет такой же тип», процесс преобразования закончен.

В качестве примера рассмотрим, в каком порядке выполняется оценка следующего выражения. В нем f имеет тип float, i — тип int, I — long int, s — переменная типа short int. f * i + I / s

1 В главе 13 кратко описывается тип bit field.

Рассмотрим сначала

умножение f на i, то есть умножение переменной типа float на переменную типа int. Из шага 3 известно, что поскольку f имеет тип float, второй операнд (i) будет тоже преобразован в тип float, и такой же тип будет иметь результат операции умножения.

Затем I делится на s, то есть выполняется деление переменной типа long int на short int. Из шага 4 известно, что short int преобразуется в int. Переходим к шагу 6. Поскольку один из операндов (1) имеет тип long int, второй операнд преобразуется в long int, и результат будет иметь такой же тип. Таким образом, это деление дает значение типа long int, причем дробная часть отбрасывается.

И, наконец, шаг 3 указывает, что поскольку один из операндов выражения имеет тип float (как результат умножения f * i), второй операнд будет преобразован в тип float, и результат будет иметь такой же тип. Таким образом, после деления I на s результат операции будет преобразован в тип float и затем прибавлен к произведению f на i. Поэтому конечный результат этого выражения будет иметь тип float.

Вы всегда можете использовать оператор приведения типа для явных преобразований, управляя оценкой конкретного выражения.

Например, если вы не хотите, чтобы при делении I на s в предыдущем выражении отбрасывалась дробная часть, то можете выполнить приведение одного из этих операндов к типу float, чтобы выполнить деление с плавающей точкой: f * i + (float) I / s

В этом выражении I будет преобразована в тип float до операции деления, поскольку оператор приведения типа имеет более высокий приоритет, чем оператор деления. Поскольку один из операндов деления будет теперь иметь тип float, другие операнды будут автоматически преобразованы в тип float, и такой же тип будет иметь результат. Расширение для знака

Если переменная типа signed int или signed short преобразуется в тип int или тип большего размера, то в результате преобразования слева тоже появляется описатель signed. Поэтому переменная типа short int, которая имеет значение -5, будет иметь значение -5 после преобразования в long int. Но если целая переменная с описателем unsigned преобразуется в тип int или тип большего размера, то расширение для знака не происходит (как и можно было ожидать).

На некоторых машинах (например, с процессорами Intel, которые используются в современных семействах компьютеров Macintosh, или с процессорами ARM, которые используются в iPhone и iTouch) символы интерпретируются как значения со знаком. Это означает, что если символ (character) преобразуется в целый тип, то происходит расширение для знака. Если используются символы из стандартного набора символов ASCII, это не создает проблем. Но если значение символа не является частью этого стандартного набора символов, для его знака может быть выполнено расширение, если символ преобразуется в целый тип. Например, на компьютерах Мае символьная константа '\377’ преобразуется в значение -1, потому что это значение является отрицательным, если рассматривать его как 8-битное значение со знаком (signed).

Objective-C позволяет объявлять символьные переменны е без знака (unsigned), что позволяет избежать этой потенциальной проблемы — переменная unsigned char не получает расширения для знака при преобразовании в целый тип; ее значение всегда больше или равно нулю. Для обычного 8-битного символа символьная переменная со знаком имеет диапазон значений от -128 до +127 включительно. Символьная переменная без знака имеет диапазон значений от О до 255 включительно.

Если ваши символьные переменные должны получать расширение для знака, вы можете объявить такие переменные с типом signed char. В главе 15 вы узнаете о многобайтных символах Unicode. Это предпочтительный способ работы со строками. Упражнения

Поделиться с друзьями: