355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Стивен Кочан » Программирование на Objective-C 2.0 » Текст книги (страница 15)
Программирование на Objective-C 2.0
  • Текст добавлен: 19 сентября 2016, 13:02

Текст книги "Программирование на Objective-C 2.0"


Автор книги: Стивен Кочан



сообщить о нарушении

Текущая страница: 15 (всего у книги 32 страниц)

Тип по умолчанию для возвращаемого значения отличается от методов. Если для метода не указан тип возвращаемого значения, компилятор предполагает, что метод возвращает значение типа id. Но для метола тоже следует указывать тип возвращаемого значения. Объявление типов возвращаемых значений и типов аргументов

По умолчанию компилятор Objective-C предполагает тип int для возвращаемого значения. Точнее говоря, если вызывается функция, компилятор предполагает, что эта функция возвращает значение типа int, за исключением следующих случаев.

Эта функция определена в программе до того, как встретился вызов этой функции.

Значение, возвращаемое функцией, объявлено до того, как встретился вызов этой функции. Объявление типов возвращаемого значения и аргументов для функции называется объявлением прототипа (prototype).

Объявление функции используется не только для объявления типа возвра-щаемого значения функции, но также для того, чтобы указать компилятору, сколько аргументов и каких типов передавать функции. Это аналогично объяв-лению методов в секции @interface при объявлении нового класса.

Чтобы объявить absoluteValue как функцию, которая возвращает значение типа float и при и и мает один аргумент типа float, можно использовать следующее объявление прототипа. float absoluteValue (float);

Достаточно указать только тип аргумента в круглых скобках, но не его имя. Вы можете дополнительно указать после типа «фиктивное» имя, например, float absoluteValue (float х);

Это имя не обязательно должно совпадать с именем в определении функции (в любом случае, компиля тор его игнорирует).

Для надежности при объявлении прототипа скопируйте первую строку из фактического объявления функции. Не забудьте поставить в конце точку с за– пятой. Если функция принимает переменное число параметров (как в случае с NSLog и scant), об этом нужно информировать компилятор. Объявление void NSLog (NSString *format, ...);

указывает компилятору, что NSLog принимает объект типа NSString в качестве первого аргумента, после которого следует любое число дополнительных аргу-ментов. NSLog объявляется в специальном файле Foundation/Foundation.h , и поэтому в начале каждой программы мы помещаем строку #import

Без этой строки компилятор может предполагать, что NSLog принимает фиксированное число аргументов, что может привести неверному генерируе-мому коду.

Компилятор автоматически преобразует числовые аргументы в соответствующие типы при вызове функции, если вы поместили определение функции или объявили функцию и ее ар1ументы до этого вызова.

Ниже приводятся некоторые сведения о функциях.

По умолчанию компилятор предполагает, что функция возвращает значение типа int.

Определяя функцию с возвращаемым значением типа int, определите ее та-ким же образом.

Определяя функцию, которая не возвращает никакого значения, определите ее с ключевым словом void.

Компилятор преобразует аргументы для согласования с аргументами, кото-рые ожидает функция, только если вы ранее определили или объявили эту функцию. Для надежности объявляйте все функции в своей программе, даже если они определены до их вызова. Лучше всего поместить объявления ваших функций в header-файл и затем просто импортировать этот файл в ваши модули.

Функции по умолчанию являются внешними (external). Область действия по умолчанию для функции устроена так, чтобы ее могли вызывать любые функции или методы, содержащиеся в любых файлах, которые связаны с этой функцией. Вы можете ограничить область действия функции, сделав ее статической. Для этого нужно поместить перед объявлением функции ключевое слово static, как показано ниже. static int ged (int u, int v) { ... }

Статическую функцию могуг вызывать только другие функции или методы, которые находятся в одном файле с определением этой функции. Функции, методы и массивы

Чтобы передать функции или методу один элемент массива, его нужно указать как аргумент. Например, если функция squareRoot вычисляет квадратные корни, и мы хотим получить квадратный корень от averages[i] и присвоить результат переменной sq_root_result. то можно написать оператор sq_root_result = squareRoot (averagesfi]);

Передача всего массива функции или методу выполняется иначе. При вызове функции или метода нужно указать только имя этого массива (без индексов). Например, если grade_scores был объявлен как массив, содержащий 100 эле-ментов, выражение minimum (grade_scores)

будет передавать все 100 элементов, содержащихся в массиве grade_score$, функции с именем minimum. Конечно, функция minimum должна ожидать передачи всего массива как ар|умента и иметь соответствующее объявление формального параметра.

Следующая функция ищет минимальное целое значение в массиве с ука-занным количеством элементов. // Функция для поиска минимума в массиве int minimum (int values[], int numElements) { int minValue, i; minVaiue = values[0]; for (i = 1; i < numBements; ++i) if ( values[i] < minValue ) minValue = values[i]; return (minValue); }

В соответствии с определением, функция minimum принимает два аргумента. Первый аргумент – это массив, минимум значений которого мы хотим найти, а второй аргумент – это число элементов в данном массиве. Прямоугольные скобки, которые непосредственно следуют после values в заголовке функции, информируют компилятор Objective-C, что values – это массив с целыми значе-ниями. Компилятору не нужен размер этого массива.

Формальный параметр numElements используется как верхний предел в опе-раторе for. С помощью оператора for выполняется перебор всего массива от элемента values[1] до последнего элемента vaiues[numElements-1].

Если функция или метод изменяет значение элемента массива, это изменение вносится в исходный массив, переданный функции или методу. Это изменение остается в силе даже после того, как функция или метод закончит свое выполнение.

Работа с целым массивом происходит иным образом, чем с простой пере-менной или элементом массива (значения которых функция или метод не может изменить). Мы уже говорили, что при вызове функции или метода значения, передаваемые как аргументы, копируются в соответствующие формальные параметры, но при работе с массивами содержимое всего массива не копируется R массив формального параметра. Вместо этого передается указатель, пока-зывающий, где в памяти компьютера размещен этот массив. Таким образом, любые изменения, внесенные в массив формального параметра, на самом деле вносятся в исходный массив, а нс в копию этого массива. Поэтому при выходе из функции или метода эти изменения остаются действительными. Многомерные массивы

Элемент многомерного массива можно передавать функции или методу как обычную переменную или элемент одномерного массива. В строке result = squareRoot (matrix[i][j]);

происходит вызов функции squareRoot с передачей в качестве аргумента значе-ния, содержащегося в matrix[i][j].

В качестве аргумента можно передать весь многомерный массив так же, как одномерный массив: нужно просто указать имя самого массива. Например, если матрица measuredValues объявлена как двумерный массив с целыми значениями, то оператор Objective-C scalarMultipiy (measuredValues, constant);

можно использовать для вызова функции, которая умножает каждый элемент этой матрицы на значение константы. Из этого, конечно, следует, что сама фун-кция может изменять значения, содержащиеся в массиве measuredValues. Все, что говорилось выше об одномерных массивах, применимо и к многомерным массивам. Изменения, вносимые внутри функции в любой элемент массива фор-мального параметра, являются также изменениями в массиве, который был передан функции.

Мы уже говорили, что в случае объявления одномерного массива как фор-мального параметра нам не нужен конкретный размер массива. Мы просто ис-пользуем пару прямоугольных скобок, чтобы информировать компилятор Objective-C, что параметр является массивом. В случае многомерных массивов это применимо лишь отчасти. Для двумерного массива можно не указывать число строк массива, но объявление должно содержать число столбцов массива. Оба объявления int arrayValues[100][50]

и int arrayValues[][50]

являются допустимыми для массива формального параметра с именем arrayValues, который содержит 100 строк и 50 столбцов. Однако оба объявления int arrayValues[100][]

и int arrayValues[][]

не являются допустимыми, поскольку необходимо указать число столбцов мас-сива. 13.3. Структуры

Помимо массивов, язык Objective-C содержит еще одно средство группирования элементов – структуры.

Предположим, что нам нужно нам нужно сохранить внутри программы дату (например, 18/07/09), чтобы использовать ее для заголовка результатов программы или для вычислений. Обычный способ сохранения даты – это присвоить месяц целой переменной с именем month, день – целой переменной day и год – целой переменной year. Поэтому здесь вполне подойдут операторы int month = 7, day = 18, year = 2009;

Но как быть, если в программе требуется сохранять несколько дат? Следо-вало бы сгруппировать эти наборы из трех переменных.

В языке Objective-C мы можем определить структуру с именем date (дата), которая состоит из трех компонентов, представляющих месяц, день и год. Син-таксис такого определения достаточно очевиден. struct date { int month; int day; int year; };

Только что определенная структура date содержит три целых компонента с именами month, day и year. Такое определение даты – новый тип переменных, переменные теперь можно объявлять с типом struct date, как в следующем опре делении: struct date today;

Мы можем определить переменную такого же типа purchaseDate (дата покупки) с помощью отдельного определения struct date purchaseDate;

или просто включить оба определения в одну строку: struct date today, purchaseDate;

В отличие от переменных типа int, float или char, при работе со структурными переменными требуется специальный синтаксис. Для доступа к компоненту структуры нужно указать имя структурной переменной, после которого следует точка (она называется оператором «точка» – dot operator) затем имя компо нента структуры. Например, чтобы задать значение 21 для компонента day переменной today, нужно написать today.day = 21;

Отметим, что между именем переменной, точкой и именем компонента не допускаются пробелы.

Вы можете возразить, что мы уже использовали, казалось бы, такой же опе-ратор для вызова свойства объекта. Вспомним, что оператор myRect.width = 12;

вызывает метод-установщика (с именем sefWidth) объекта класса Rectangle, передавая ему значение аргумента 12. Здесь нет никакой путаницы: компилятор сам определяет, что находится справа от оператора «точка», – структура или объект, – и выполняет соответствующую обработку.

Вернемся к примеру struct date, чтобы задать значение 2010 для компонента year в структуре today. today.year = 2010;

И, наконец, чтобы проверить, что значение month равно 12, можно исполь-зовать оператор if (today, month == 12 ) next_month = 1;

В программе 13.6 реализуется то, что мы обсуждали выше. #import int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; struct date { int month; int day; int year; }; struct date today; today.month = 9; today.day = 25; today.year = 2009; NSLog (@"Today’s date is %i/%i/%.2i.", today.month, today.day, today.year % 100); [pool drain]; return 0; }

Вывод программы 13.6 Today’s date is 9/25/09. (Текущая дата – 25.9.09)

В первом операторе внутри main определяется структура с именем date, которая состоит из трех целых компонентов: month, day и year. Во втором операторе объявляется переменная today с типом struct date. Таким образом, в первом опе-раторе просто определяется, как выглядит структура даты для компилятора Objective-C, и не требуется никакого резервирования памяти внутри компьютера. Во втором операторе объявляется переменная типа struct date, и здесь происходит резервирование памяти для хранения трех целых компонентов структурной переменной today.

После присваивания значений соответствующий вызов NSLog выводит зна-чения, содержащиеся в этой структуре. Вычисляется остаток отделения today.year на 100, поэтому функция NSLog выводит для года только две цифры. Символы формата %.2i в обращении к NSLog указывают вывод не менее двух символов, в результате чего для года выводится ведущий нуль.

При вычислении выражений компоненты структуры подчиняются таким же правилам, что и обычные переменные в языке Objective-C. Деление целого ком-понента структуры на другое целое значение выполняется как деление целых, например century = today.year /100+ 1;

Напишем несложную программу, которая принимает на входе текущую дату и выводит завтрашнюю дату (tomorrow). На первый взгляд это кажется совсем простой задачей. Нужно запросить у пользователя ввод текущей даты и затем вычислить завтрашнюю дату с помощью следующего набора операторов. tomorrow.month = today.month; tomorrow.day = today.day + 1; tomorrow.year – today.year;

Конечно, для большинства дат это подходит, но два случая будут реализованы неверно.

Текущая дата приходится на конец месяца.

Текущая дата приходится на конец года (то есть на 3 1 декабря). Чтобы определить, приходится ли текущая дата на конец месяца, нужно задать массив целых значений, соответствующих числу дней каждого месяца.

Поиск в этом массиве даст число дней месяца (см. программу 13.7). // Программа определения завтрашней даты #import struct date { int month; int day; int year; }; // Функция для вычисления завтрашней даты struct date dateUpdate (struct date today) { struct date tomorrow; int numberOfDays (struct date d); if (today.day != numberOfDays (today)) { tomorrow.day = today.day + 1; tomorrow.month = today.month; tomorrow.year = today.year; } else if (today.month == 12) // end of year { tomorrow.day = 1; tomorrow.month = 1; tomorrow.year = today.year + 1; } else { // конец месяца tomorrow.day = 1; tomorrow.month = today.month + 1; tomorrow.year = today.year; } return (tomorrow); } // Функция для поиска числа дней в месяце int numberOfDays (struct date d) { int answer; BOOL isLeapYear (struct date d); int daysPerMonth[12] = { 31,28, 31, 30, 31, 30, 31, 31,30, 31,30, 31 }; if (isLeapYear (d) == YES && d.month == 2) answer = 29; else answer = daysPerMonth[d. month – 1]; return (answer); } // Функция, определяющая, является ли год високосным BOOL isleapYear (struct date d) { if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0 ) return YES; else return NO; } int main (int argc, char *argv[]) { NSAutoreleasePool * poo! = [[NSAutoreleasePool alloc] init]; struct date datellpdate (struct date today); struct date thisDay, nextDay; NSLog (@nEnter today’s date (mm dd yyyy):"); scanf ("%i%i%i", SthisDay.month, SthisDay.day, &thisDay.year); nextDay = dateUpdate (thisDay); NSLog (@"Tomorrow’s date is %i/%i/%.2i.",nextDay.month, nextDay .day, nextDay.year % 100); [pool drain]; return 0; }

Вывод программы 13.7 Enter today’s date (mm dd yyyy): (Введите текущую дату (мм дд rrrr) 2 28 2012 Tomorrow’s date is 2/29/12. (Завтрашняя дата)

Вывод программы 13.7 (повторный запуск) Enter today’s date (mm dd yyyy): 10 2 2009 Tomorrow’s date is 10/3/09.

Вывод программы 13.7 (повторный запуск) Enter today’s date (mm dd yyyy): 12 31 2010 Tomorrow’s date is 1/1/10.

Хотя мы не работаем в этой программе с классами, здесь был импортирован файл Foundation.!!, поскольку нам нужен тип B00L и определенные имена YES и N0. Они определены в этом файле.

Отметим, что определение структуры данных представлено в первую очередь и вне какой-либо функции. Определения структур данных действуют аналогично переменным. Если структура определена внутри какой-либо функции, только эта функция «знает» о ее существовании, и тогда это локальное определение структуры. Если структура определена вне любой функции, это определение является глобальным. Глобальное определение структуры позволяет объявлять любые последующие переменные (внутри или вне функции) как структуру этого типа. Определения структур, которые используются в нескольких файлах, обычно централизуются водном header-файле и затем импортируются в те файлы, где нужна эта структура.

Внутри процедуры main объявление struct date dateUpdate (struct date today);

указывает компилятору, что функция dateUpdate принимает в качестве аргумента структуру типа date и возвращает структуру такого же типа. Это объявление не обязательно, поскольку компилятор уже «видел» конкретное объявление функции в этом файле, но принято в практике надежного программирования. Если вы в дальнейшем разделите определение этой функции и main на отдельные исходные файлы, объявление будет необходимо.

Как и для обычных переменных (но не для массивов), любые изменения, которые вносятся функцией в значения, содержащиеся в аргументе структуры, не оказывают влияния на исходную структуру. Они влияют только на копию этой структуры, которая создастся при вызове функции.

После ввода даты и ее сохранения в структурной переменной thisDay типа date происходит вызов функции dateUpdate. nextDay = dateUpdate (thisDay);

Здесь происходит вызов функции dateUpdate с передачей этой функции струк-туры даты thisDay.

Внутри функции dateUpdate объявление прототипа int numberOfDays (struct date d);

информирует компилятор Objective-C, что функция numberOfDays возвращает целое значение и принимает один аргумент типа struct date.

Оператор if (today.day != numberOfDays (today))

указывает, что структура today должна передаваться как аргумент функции numberOTOays. Внутри этой функции должно быть соответствующее объявление, информирующее систему, что аргументом должна быть структура, как в следующей строке. int numberOfDays (struct date d)

Сначала в функции numberOfDays нужно выполнить проверку на високосный год и определить, не является ли месяц февралем. Для первой проверки вызы-вается другая функция с именем isLeapYear.

Функция isLeapYear вполне понятна; она проверяет год, содержащийся в структуре типа date, которая передается как аргумент, и возвращает значение YES в случае високосного года или N0 в противном случае.

Вы должны понять иерархию вызовов функций в программе 13.7. функция main вызывает dateUpdate, которая вызывает numberOfDays, которая, в свою очередь, вызывает функцию isLeapYear. Инициализация структур

Инициализация структур аналогична инициализации массивов: значения ком-понентов просто перечисляются в фигурных скобках с применением запятой в качестве разделителя.

Чтобы инициализировать переменную today структуры типа date, задав зна-чение Июль, 2 число, 20П год, можно использовать оператор struct date today = { 7, 2, 2011 };

Как и при инициализации массива, можно указывать значения не для всех компонентов структуры. Например, в операторе struct date today = {7 };

задается значение 7 для компонента today.month, но не задаются начальные зна-чения для today.day и today.year. В таких случаях начальные значения по умолча-нию не определены.

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

например, struct date today = {.month = 7, .day = 2, .year = 2011 };

и struct date today = {.year = 2011 };

В последнем примере этой структуры задается только значение года, равное 2011. Остальные два компонента не определены. Массивы структур

Работа с массивами структур не представляет особых сложностей. Например, в struct date birthdays[15];

определяется массив birthdays (дни рождения), содержащий 1 S элементов типа Struct date. Нужный элемент в массиве структур указывается естественным образом. Например, чтобы задать для второго элемента в массиве birthdays дату дня рождения 22 февраля 1996 г., можно написать последовательность birthdays[1].month = 2; birthdays[1]. day = 22; birthdays[1].year = 1996;

Оператор n = numberOfDays (birthdaysfO]);

передает первый элемент этого массива функции numberOfDays, чтобы опреде-лить, сколько дней содержит указанный в дате месяц. Структуры внутри структур

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

Вы уже видели, как логически группировать месяц, день и год (month, day и year) в структуре с именем date. Предположим, что у нас есть аналогичная струк-тура с именем time для группирования часов, минут и секунд (hour, minutes и seconds). В некоторых приложениях может потребоваться логическая группи-ровка структур date и time – например, для списка событий с определенной датой и временем.

Из предыдущего описания следует, что нам нужны удобные средства, объе-диняющие дату и время. Это можно сделать в Objective-C, определив новую структуру (например, date_and_time), компоненты которой содержатся в элементах date и time. struct date_and_time { struct date sdate; struct time stime; };

Первый компонент этой структуры имеет тип struct date и называется sdate. Второй компонент структуры date_and_time имеет тип struct time и называется stime. В этом определении структуры date_and_time требуется, чтобы структура date и структура time были предварительно определены для компилятора.

Теперь можно определять переменные типа struct date_and_time: struct date_and_time event;

Для указания ссылки на структуру date в переменной event используется тот же синтаксис: event.sdate

Мы можем вызвать функцию dateUpdate, указав дату в качестве аргумента, чтобы получить результат в том же месте. event.sdate = dateUpdate (event.sdate);

То же самое можно сделать для структуры time, содержащейся в структуре date_and_time. event.stime = timeUpdate (event.stime);

Для указания определенного компонента внутри одной из этих структур нужно добавить точку и имя этого компонента: event.sdate.month = 10;

В этом операторе задается значение 10 (октябрь) для компонента month структуры date переменной event. В операторе ++event.stime.seconds;

значение компонента seconds структуры time увеличивается на 1.

Инициализировать переменную event можно уже известным способом: struct date_and_time event = {{ 12, 17, 1989 }, { 3, 30,0}};

Здесь для переменной event задается дата 17 декабря 1989 г. и время 3:30:00.

Массив структур date_and_time можно задать с помощью объявления struct date_and_time events[100];

Здесь объявляется, что массив events содержит 100 элементов типа struct date_and_time. Для указания 4-го элемента date_and_time в массиве нужно написать events[3], а для 25-й даты в массиве при обращении к функции dateUpdate нужно написать events[24].sdate = dateUpdate (events[24].sdate);

Чтобы записать 12 часов дня в первый элемент этого массива, применяется следующий набор операторов. events[0].stime.hour = 12; events[0].stime.minutes = 0; events[0].stime.seconds = 0; Дополнительно о структурах

Определять структуру можно достаточно гибко. Во-первых, можно объявить переменную с определенным структурным типом одновременно с объявлением структуры. Для этого достаточно включить имя переменной (переменных) с завершающей точкой с запятой в определение структуры. Например, в следую-щем операторе определяется структура date и объявляются переменные todaysDate и purchaseDate этого типа. struct date { int month; int day; int year; } todaysDate, purchaseDate;

Вы можете присвоить этим переменным начальные значения обычным об-разом. Ниже определяется структура date и переменная todaysDate с указанием начальных значений. struct date { int month; int day; int year; } todaysDate = { 9, 25, 2010 };

Если все переменные определенного структурного типа определяются вместе с определением структуры, то можно не задавать имя структуры. Ниже оп-ределяется массив с именем dates, содержащий 100 элементов. struct { int month; int day; int year; } dates[ 100);

Каждый элемент является структурой, содержащей три целых компонента: month, day и year. Поскольку здесь не указывается имя структуры, при последующем объявлении переменных того же типа структуру придется явно определить снова. Битовые поля

В Objective-C имеются два способа упаковки информации. Первый способ – это представление данных внутри переменной целого типа и последующий доступ к нужным битам с помощью побитовых операций, описанных в главе 4.

Второй способ – это определение структуры упакованной информации с помощью конструкции Objective-C, которая называется битовым полем (bitfield). Для этого применяется специальный синтаксис в определении структуры, по-зволяющий определять поле битов и присваивать ему имя.

Для определения битовых полей можно определить структуру, например, с именем packedStruct. struct packedStruct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int type:4; unsigned int index:9; }

В соответствии с этим определением, структура packedStruct состоит из пяти компонентов. Первый компонент, Н, имеет тип unsigned int. Обозначение :1 после имени компонента указывает, что компонент будет содержаться в 1 бите. Флаги f2 и f3 определяются аналогичным образом. Компонент type занимает в соответствии с определением 4 бита, а компонент index имеет длину 9 битов.

Компилятор автоматически упаковывает подряд эти битовые поля. Удобство этого подхода состоит в том, что поля переменной типа packedStruct можно указывать как обычные компоненты структуры. Например, если объявлена пе-ременная packedData struct packedStruct packedData;

вы можете легко присвоить значение 7 полю type переменной packedData с по-мощью простого оператора packedData.type = 7;

Можно присвоить этому полю значение переменной п с помощью оператора packed Data.type = n;

В последнем случае вы можете не думать о том, что значение п может ока-заться слишком большим, чтобы уместиться в поле type; в packedData.type будут записаны только младшие 4 бита.

Извлечь значение из битового поля тоже непрудно. Например, с помощью оператора n = packedData.type;

извлекается значение поля type переменной packedData (с автоматическим сме-щением в младшие биты, если это требуется), которое присваивается перемен-ной n.

Битовые поля можно использовать в обычных выражениях и автоматически преобразовывать их в целые значения. Например, оператор i = packed Data. index / 5 + 1;

является вполне допустимым, как и оператор if (packedData.f2)

Проверка, установлен ли флаг f2. Мы не можем точно сказать, как заполня-ются битовые поля, – слева направо или справа налево. Если они заполняются справа налево, то П будет находиться в позиции младшего бита, f2 – в битовой позиции непосредственно слева от fl, ит.д. Это не представляет проблемы, если вы не работаете с данными, которые созданы другой программой или на другой машине.

Вы можете включать обычные типы данных в структуру, содержащую бито-вые поля. Например, если нужно определить структуру, содержащую типы int, char и два 1-битовых флага, можно использовать следующее определение. struct table_entry { int count; char c; unsigned int f1:1; unsigned int f2:1; };

Битовые поля упаковываются в блоки (unit) в соответствии с порядком их следования в определении структуры, причем размер блока определяется реа-лизацией и, скорее всего, является словом. Компилятор Objective-C нс изменяет определения битовых полей, пытаясь уменьшить размер используемого про-странства.

Можно задавать битовое поле без имени, чтобы пропускать биты внутри слова. Ниже определяется структура x_entry, которая содержит 4-битовос поле с именем type и 9-битовое поле с именем count. struct x_entry { unsigned int type:4; unsigned int :3; unsigned int count:9; };

Поле без имени указывает, что поле type отделяется от поля count 3 битами.

Особым случаем является использование неименованного поля длиной 0. Его можно использовать, чтобы принудительно выровнять следующее поле в структуре с началом границы блока. Не забывайте об объектно-ориентированном программировании!

Теперь вы знаете, как определить структуру для хранения даты, и умеете писать процедуры для работы со структурой даты, А как быть с объектно-ориентиро-ванным профаммированием? Ведь вместо этого можно создать класс с именем Date и затем разработать методы для работы с объектами типа Date. Конечно, такой подход будет лучше. Несомненно, при работе с большим числом дат в программах определение класса и методов для работы с датами является более подходящим. Для таких целей Foundation framework содержит пару классов с именами NSDate и NSCatendarDate. Реализацию класса Date для работы с датами как с объектами, а не структурами мы оставляем вам в качестве упражнения. 13.4. Указатели

Указатели (Pointer) позволяют эффективно представлять сложные структуры данных, изменять значения, передаваемые в виде аргументов функциям и методам, а также проще и эффективнее работать с массивами. В конце этой главы мы расскажем, насколько они важны для реализации объектов в языке Objective-C.

Мы ввели понятие объекта в главе 8, когда описывали классы Point и Rectangle, и упомянули, что можно иметь несколько ссылок на один объект.

Чтобы понять, как действуют указатели, вы должны сначала ознакомиться с понятием косвенного обращения (indirection). Мы часто встречаемся с этим по-нятием в повседневной жизни. Предположим, мне нужно купить новый картридж с тонером для моего принтера. В компании, где я работаю, все приобретения выполняются через отдел снабжения, поэтому я звоню сотруднику этого отдела и прошу заказать для меня новый картридж. Он звонит в местный магазин запчастей, чтобы заказать картридж. Для получения картриджа я применяю косвенный подход вместо прямого заказа картриджа в магазине.

Понятие косвенного подхода можно применить и к указателям в Objective– С. Указатель – это средство косвенного доступа к значению определенного эле-мента данных. Расмотрим, как действуют указатели. Орсделим переменную с именем count int count = 10;

С помощью следующего объявления мы можем определить другую переменную с именем intPtr для косвенного доступа к значению переменной count. int *intPtr;

Звездочка показывает, что переменная intPtr является указателем на тип int. Это означает, что программа будет использовать intPtr для косвенного доступа к значению одной или нескольких целых переменных.

Мы уже использовали в предыдущих программах оператор & при обращении к scant. Этот унарный оператор, который называют адресным (address) опе-ратором, создает указатель на переменную в Objective-C. Например, если х – переменная определенного типа, то выражение &х является указателем на эту переменную. Если нужно, вы можете присвоить выражение &х любой перемен-ной-указателю, объявленной как указатель на тип, который имеет переменная х. Оператор intPtr = &count;


    Ваша оценка произведения:

Популярные книги за неделю