Битовые поля структур и объединений
Внутри структур и объединений могут в качестве их компонентом (элементов) использоваться битовые поля. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов (в компиляторе ВС++ от 1 до 16 бит). Битовые поля могут быть только элементами структур, объединений (и, как увидим в дальнейшем, классов), т.е. битовые поля не могут появляться как самостоятельные объекты программ. Битовые поля не имеют адресов, т.е. для них не определена операция &, нет указателей и ссылок на битовые поля. Они не могут объединяться в массивы. Назначение битовых полей - обеспечить удобный доступ к отдельным битам данных. С помощью битовых полей можно формировать объекты с длиной внутреннего представления, не кратной байту. Это позволяет плотно "упаковывать" информацию и тем самым экономить память, например, при работе с однобитовыми флажками.
Определение структуры с битовыми полями имеет такой формат:
struct { тип_поля имя_поля: жирина_поля; тип_поля имя_поля: ширина_поля;
} имя_структуры;
Здесь тип_поля - один из базовых целых типов int, unsigned int (сокращенно unsigned), signed int (сокращенно signed), char, short, long и их знаковые и беззнаковые варианты. (В языке Си стандарт ANSI допускает только знаковый или беззнаковый вариант типа int.)
Рис. 7.3 Варианты размещения в памяти битовых полей структуры
имя_поля - идентификатор, выбираемый пользователем; ширина-поля - целое неотрицательное десятичное число, значение которого , обычно не должно превышать длины слова конкретной ЭВМ.
Таким образом, диапазон возможных значений ширины..поля существенно зависит от реализации. В компиляторах ТС++ и ВС++ ширина-поля может выбираться в диапазоне от 0 до 16. Пример определения структуры с битовыми полями:
struct { int а: 10; int b:14; } хх, *рх;
Для обращения к битовым полям используются те же конструкции, что и для обращения к обычным элементам структур:
имя_структуры.имя_поля
укаэатель_на_структуру->имя_поля
ссылка_на_структуру.имя_поля
(* указатель_на_струхтуру).имя_поля
Например, для введенной структуры хх и указателя рх допустимы такие операторы:
хх.а = 1; рх = &хх; рх->b = 48;
От реализации зависит порядок размещения полей структуры в памяти IВМ. Поля могут размещаться как справа налево, так и слева направо. Кроме того, реализация определяет, как размещаются в памяти битовые ноля, длина которых не кратна длине слова и(или) длине байта (рис. 7.3). Для компиляторов, работающих на IBM PC, поля, размещенные в начале описания структуры, имеют младшие адреса. Именно такое размещение изображено на рис. 7.3.
В компиляторах часто имеется возможность изменять размещение битовых полей, выравнивая их по границам слов или выполняя плотную упаковку. Некоторые возможности влиять на размещение битовых полей в памяти имеются и на уровне синтаксиса самого языка Си++. Во-первых, мри определении битового поля разрешается не указывать его имя. В этом случае (когда указаны только двоеточие и ширина поля) в структуру вводятся неиспользуемые (недоступные'» биты, формирующие промежуток между значимыми полями. Например
Рис. 7.4. Структура с безымянным полем
В структуре уу между полем int a: 10 и полем int Ь:14 размещаются 6 бит, не доступных для использования. Их назначение - выравнивание полей по плану программиста (рис. 7.4).
Битовые поля в объединениях используются для доступа к нужным битам того или иного объекта, входящего в объединение. Например, следующее объединение позволяет замысловатым способом сформировать код символа ‘D’ (равный 68):
union { char simb;
struct { int x:5; int y:3; ) hh; } cod;
cod.hh.x = 4; cod.hh.y = 2; cout « cod.simb; // Выведет на экран символ 'D'
Рис. 7.5 иллюстрирует формирование кода 68, соответствующего символу 'D'.
Рис. 7.5 Объединение со структурой из битовых полей
Для иллюстрации особенностей объединений и структур с битовыми полями рассмотрим следующую программу:
//Р7-05.СРР - битовые поля, структуры, объединения tinclude <iostream.h>
// Функция упаковывает в один байт остатки от деления // на 16 двух целых чисел - параметров: unsigned char cod(int a,int b) { union { unsigned char z;
struct { unsigned int x:4; // Младшие биты unsigned int y:4; // Старшие биты } hh; } un ;
un.hh.x = a % 16; un.hh.y = b % 16; return un.z;
)
// Функция изображает на экране двоичное представление
// байта-параметра:
void binar(unsigned char ch){
union { unsigned char ss;
struct { unsigned aO:l;
unsigned al:1;
unsigned a2:1;
unsigned a3:1;
unsigned a4:1;
unsigned a5:l;
unsigned аб:1;
unsigned a7:1;
} byte;
} cod;
cod.ss = ch; // Занести значение параметра в объединение // Выводим биты внутреннего кода значения параметра: cout « "\nHOMEPA БИТОВ: 76543210"; cout « "ХпЗначения битов:";
cout « "\t" « cod.byte.a7 « " " « cod.byte.аб; cout « " " « cod.byte.a5 « "• " « cod.byte.a4; cout « " " « cod.byte.a3 « " " « cod.byte.a2; cout « " " « cod.byte.al « " " « cod.byte.aO; cout « "\n";
*
void main() {
int k;
int в, n;
cout « "\nm = "; cin » m;
cout « "n = "; cin » n;
k - cod(m,n);
cout « "cod = " « k;
binar(k);
}
Возможный результат выполнения программы:
m = I <Enter>
n = 3 <Enter>
cod = 49
НОМЕРА БИТОВ: 76543210
Значения битов: 00110001
Результат еще одного выполнения программы:
m = 0 <Enter>
n = I <Enter>
cod =16
НОМЕРА БИТОВ: 76543210
Значения битов: 00010000
Комментарии в тексте программы и приведенные результаты объясняют особенности программы. В функциях cod() и binar() использованы объединения, включающие структуры с битовыми полями. В функции cod() запись данных выполняется в битовые поля структуры hh, входящей в объединение un, а результат выбирается из того же объединения un, но как числовое значение байта. В функции binary() обратное преобразование - в нее как значение параметра передается байт, содержимое которого побитово "расшифровывается" за счет обращения к отдельным полям структуры byte, входящей в объединение cod.
Одно из принципиальных отличий языка Си++ от языка Си -возможность включения в структуры и объединения не только данных, но и функций. В этом случае структурный тип или объединяющий тип становится определением класса.
Дата добавления: 2020-12-11; просмотров: 400;