Битовые поля структур и объединений


Внутри структур и объединений могут в качестве их компонентом (элементов) использоваться битовые поля. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов (в компиляторе ВС++ от 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; просмотров: 395;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

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

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.012 сек.