Шрифт:
В соответствии с этим определением, структура 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 для косвенного доступа к значению одной или нескольких целых переменных.