Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Си++ Занятие 10.doc
Скачиваний:
5
Добавлен:
19.11.2019
Размер:
123.39 Кб
Скачать

9.7 Битовые поля

Особую разновидность структур представляют собой битовые поля. Битовое поле – это последовательность соседних битов внутри переменной целого типа.

Битовые поля применяются там, где необходимо манипулировать отдельными битами памяти. Для чего это нужно? В основном для управления оборудованием. Например, внешним устройством компьютера или автоматической линией на производстве. Чтобы автоматизировать какой-либо процесс, необходимо управлять нестандартным оборудованием, всевозможными датчиками, манипуляторами, моторами и т.д. все эти устройства могут быть подключены к компьютеру через устройства, называемые контроллерами.

Отдельные биты или группы бит контроллера служат для связи внешнего устройства с компьютером, записывая и считывая отдельные биты контроллера, компьютер управляет внешним устройством. Поэтому неплохо было бы иметь возможность работать с группами бит как с обычными переменными, для этого и предусмотрены битовые поля.

Битовое поле является элементом структуры и обеспечивает доступ к отдельным битам памяти, при этом запрещается:

  • объявлять битовые поля вне структур,

  • организовывать массивы битовых полей,

  • применять к полям операцию определения адреса.

Определение типа структуры с битовыми полями имеет следующий вид:

struct {unsigned имя_поля 1: длина_поля 1;

insigned имя_поля 1: длина_поля 1;

}

Поля могут иметь тип signed int или unsigned int и занимать от одного до 16 бит. В полях типа signed крайний левый бит является знаковым.

Правила работы с битовыми полями:

  • поля размещаются в машинном слове в направлении от младших битов к старшим,

  • длина определяет число бит, отведенное полю, и задается целым выражением или константой,

  • поле нулевой длины заставляет компилятор перейти к следующему слову (выравнивание на границу слова).

Пример 13.

struct prim

{int a:2; //1 и 2 биты

unsigned b:3; // 3-5 биты

int c:5; // 6-10 биты

int d:0; //выравнивание на границу слова

unsigned e:5; // 1-5 биты второго слова

} i, j, k;

Данная структура обеспечивает размещение данных в двух словах. Последние 6 бит первого слова не определены. В примере использовано явное выравнивание на границу слова. В некоторых случаях эта операция проводится компилятором автоматически. Следующий пример демонстрирует это:

struct prim

{int a:2; //1 и 2 биты

unsigned b:3; // 3-5 биты

int c:5; // 6-10 биты

unsigned e:6; // 1-6 биты второго слова

} i, j, k;

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

При определении структуры можно дать имена битовым полям, отражающие из назначение, что будет облегчать понимание текста программы.

9.8 Объединения или смеси

Третий из определяемых пользователем типов данных – это объединение, или союз. Объединение подобно структуре, однако в каждый момент времени может использоваться (или, другими словами, быть ответным) только один из его элементов.

Объединение – это некоторая переменная, которая может хранить (в разное время!) объекты различного типа и размера.

Общий вид определения объединения:

union имя_типа {список_определений}

имя_переменной [, имя_переменной];

Главной особенностью объединения является то, что для всех элементов списка_определений выделяется одна и та же область памяти, т.е. они перекрываются. Иными словами, объединение через разные поля дает доступ к одному и тому же содержимому, т.е. программа интерпретирует это содержимое по-разому.

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

Пусть задано следующее определение объединения:

union range // Размеры переменных

{ int ir; // 2 байта

float fr; // 4 байта

char cr; // 1 байт

} z;

В данном объединении определены элементы разного типа. Размер переменной z будет равен размеру самого большого из трех приведенных типов, т.е. 4 байтам. В один и тот же момент времени z может иметь значение только одной из переменных ir, fr или cr.

Доступ к элементам объединения осуществляется тем же способом, что и к структурам:

z.ir – переменная z трактуется как int;

z.fr - переменная z трактуется как float;

z.cr - переменная z трактуется как char.

Элементом объединения может быть массив.

Пример 14.

//Определение объединения (союза)

union tu

{ long a;

int b[2];

char k[4];

};

union tu u1, *au, mu[5]; //объявление трех переменных типа “union tu”

u1.a; //обращение к u1 как к типу long

u1.k[2]; //обращение к u1 как к типу char

au=mu; //установка указателя на массив объединений mu

au->b[1];

mu[2].k[3];

Здесь определение нового типа данных “union tu” и создание объектов этого типа происходит раздельно. Объявлены следующие объекты: переменная u1, указатель au на объединение и массив объединений mu[5].

Обращение к элементам объединения:

u1.a – это трактовка переменной u1 как типа long,

u1.k[2] - переменная u1 имеет тип char, и значение k[2],

au->b[1] – указатель au установлен на первый элемент массива mu, а именно на mu[0], именно в этом элементе выбирается поле b[1],

mu[2].k[3] – дает доступ к четвертому элементу массива k (к элементу с номером 3) в третьем элементе массива объединений mu.

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

Объединения можно использовать для экономии памяти при работе с большими объемами данных. Следующий пример иллюстрирует такой подход.

Пример 15. Экономия памяти при работе с картотекой.

union

{ char fio[30];

char adres[80];

int vozrast;

int telefon;

} inform;

inform.fio = base[k].fio; // работа с полем fio

inform.adres = base[k].adres; // работа с полем adres

В данном примере данные из структуры base, хранящей информацию, записываются в объект inform для текущей работы. При этом отметим, что можно обрабатывать только тот элемент, который получил значение, например, после присвоения значения элементу inform.fio не имеет смысла обращаться к другим элементам до тех пор, пока они, в свою очередь, не будут определены. Разумеется, этот прием можно использовать только для текущей обработки информации, но никак не для ее хранения.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]