Программирование на Objective-C 2.0
Шрифт:
извлекается значение поля type переменной packedData (с автоматическим сме-щением в младшие биты, если это требуется), которое присваивается перемен-ной n.
Битовые поля можно использовать в обычных выражениях и автоматически преобразовывать их в целые значения. Например, оператор i = packed Data. index / 5 + 1;
является вполне допустимым, как и оператор if (packedData.f2)
Проверка, установлен ли флаг f2. Мы не можем точно сказать, как заполня-ются битовые поля, — слева направо или справа налево. Если они заполняются справа налево, то П будет находиться в позиции младшего бита, f2 - в битовой позиции непосредственно слева от fl, ит.д. Это не представляет проблемы, если вы не работаете с данными, которые созданы другой программой или на другой машине.
Вы можете
Битовые поля упаковываются в блоки (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;задаст косвенную связь между intPtr и count. Адресный оператор 8 присваивает переменной intPtr не значение переменной count, а указатель на переменную count. На рис. 13.1 показана связь между intPtr и count. Линия со стрелкой показывает, что intPtr содержит не само значение count, а указатель на переменную count.
Рис. 13.1. Указатель на переменную целого типа
Чтобы указать содержимое count с помощью переменной-указателя intPtr, ис-пользуется оператор косвенного обращения «звездочка» (*). Если переменная х была определена с типом int, то оператор х = *intPtr;
присвоит переменной х значение, которое указывается путем косвенного обра-щения через intPtr. Поскольку выше мы задали, что intPtr указывает на переменную count, результатом этого оператора будет присваивание переменной х значения, содержащегося в переменной count (10).
В программе 13.8 показано использование двух основных операторов для указателей: адресного оператора (&) и оператора косвенного обращения (*). // Программа, показывающая использование указателей #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int count = 10, x; int *intPtr; intPtr = &count; x = *intPtr; NSLog (@"count = %i, x = %i", count, x); [pool drain]; return 0; }
Вывод программы 13.8 count = 10, x = 10
Переменные count и x объявляются обычным образом как целые переменные. В следующей строке переменная intPtr к объявляется ак «указатель на тип int». Эти две строки можно было бы объединить в одну: int count = 10, х, *intPtr;
После этого к переменной count применяется адресный оператор (&), результатом которого является создание указателя на эту переменную, который затем присваивается переменной intPtr.
Выполнение строки х = *intPtr;
происходит следующим образом. Оператор косвенного обращения () сообщает системе Objective-C, что переменная intPtr содержит указатель на другой элемент данных. Этот указатель используется для доступа к нужному элементу данных, тип которого задан при объявлении переменной-указателя. При объявлении переменной мы сообщили компилятору, что переменная intPtr указывает на целые элементы данных, поэтому компилятор «понимает», что значение, указываемое выражением intPtr, является целым. Кроме того, в предыдущей строке мы задали, что intPtr указывает на целую переменную count, поэтому это выражение представляет косвенный доступ к значению count.
В программе 13.9 иллюстрируются некоторые интересные свойства пере-менных-указателей. В ней используется указатель на символ. #import <Foundation/Foundation.h> int main (int arge, char *argv[]) { NSAutoreleasePooi * pool = [[NSAutoreleasePool alloc] init]; char c = “Q"; char *charPtr = &c; NSLog (@"%c %c", c, *charPtr); c = '/'; NSLog (@"%c %c", c, *charPtr); *charPtr = T; NSLog (@“%c %c", c, *charPtr); [pool drain]; return 0; }
} Вывод программы 13.9 QQ // ((
Символьная переменная с определяется и инициализируется со значением 'Q'. В следующей строке этой программы определяется переменная charPtr как «указатель на тип char». Это означает, что любое значение, сохраняемое внутри этой переменной, следует интерпретировать как косвенное обращение (указатель) к символу. Этой переменной можно присвоить начальное значение обычным образом. В этой программе переменной charPtr присваивается указатель на переменную с, и для этого к переменной с применяется адресный оператор &. (Эта инициализация приведет к появлению ошибки компилятора, если определить с после этого оператора, поскольку любая переменная должна быть объявлена раньше ссылки на эту переменную в любом выражении.)