Определение битовых полей

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

Получение внутреннего представления вещественного числа

Примеры использования объединений

union bytes{

double d;

unsigned char c [sizeof (double)];

};

int main ()

{

bytes ob={199.5};

for (int j=sizeof(double)-1; j>=0; j--)

{

cout << "byte " <<j << ": ";

for (int i=128; i; i>>=1) //проход по битам

if (i & ob.c[j]) //выделение бита

cout << "1";

else cout << "0";

cout << "\n";

}

_getch();

return 0;

}

Например, внутреннее представление числа -256.5: С0 70 08 00 00 00 00 00 16

в памяти значение хранится в виде: 00 00 00 00 00 08 70 С016

Объяснение, как получено это значение, дано в разделе «Внутреннее представление вещественных чисел» лекции 8.

Использование перечислимого типа для обращения к полям объединения [1] *

int main()

{ enum paytype {CARD, CHECK}; //две формы оплаты: значения 0 и 1

paytype ptype; //определение переменной перечисляемого типа

union

{char card[25];

long check;

} info;

Возможное присваивание значения объединению:

ptype = CARD; //переменная-флаг получает значение CARD (0)

strcpy (info. card, "12345"); //объединение получает свое значение через поле card

или

ptype = paytype(1); //переменная–флаг получает значение CHECK (1)

info. check= 105l; //объединение получает свое значение через поле check

Вывод значения переменной на экран:

switch (ptype) {

case CARD: cout <<"card:" << info. card<< endl; break;

case CHECK: cout <<"check:" << info. check<< endl; break;

}

_getch();

return 0;

}

Реализуем пример по-другому.

Создадим структуру, включающую объединение и поле перечислимого типа, характеризующее форму оплаты:

int main()

{

enum paytype {CARD, CHECK}; //две формы оплаты

struct{

paytype ptype; //поле-флаг включено в состав структуры

union

{char card[25];

long check;

} info;

} str;

Возможное присваивание значения объединению:

str.ptype = paytype(0); //заполняем поле-флаг объединения, как элемента структуры

strcpy(str.info.card, "12345");//объединение, как элемент структуры,

//получает свое значение через поле card

или

str.ptype = paytype(1); //заполняем поле-флаг объединения, как элемента структуры

str.info.check= 105l; //объединение, как элемент структуры,

//получает свое значение через поле check

Вывод на экран значения объединения как элемента переменной-структуры:

switch (str.ptype) {

case CARD: cout <<"card:" << str.info.card<< endl; break;

case CHECK: cout <<"check:" << str.info.check<< endl; break;

}

_getch();

return 0;

}

Язык С++ допускает использование в структурах и объединениях в качестве полей данных особого типа полей – битовых. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов. Число связанных бит – ширина поля.

Общий синтаксис описания битового поля:

тип_поля [имя_поля]: ширина_поля;

Члены битовых полей могут иметь значения базовых целых типов (знаковых или беззнаковых). Эти ключевые слова записываются в поле «тип_поля». Для переносимости программ лучше указывать служебные слова signed или unsigned, однако заметим, что сама природа структур с битовыми полями не способствует переносимости.

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

struct имя_структурного _типа {

тип_поля1 имя_поля1: ширина_поля1;

тип_поля2 имя_поля2: ширина_поля2;

} имя_структурной_переменной;

Каждому полю выделяется столько бит, сколько задается в поле «ширина». Ссылка на битовое поле выполняется по имени, указываемому в поле «имя». Например:

struct EXAMPLE { int i:3;

unsigned j:2;

int:3;

int k: 2;

} my_struct;

Это описание включает 4 битовых поля: i из трех битов (значения от -4 до 3), j из двух битов (значения от 0 до 3), поле без имени из трех битов и поле k из двух битов (значения от -2 до 1). В памяти, отводимой под структуру EXAMPLE, битовое поле k будет расположено не непосредственно за полем j, а через три бита от него (на величину безымянного поля). Неименованное поле используется в структуре как заполнение:ничто не будет храниться в этих битах.

При ссылке на битовое поле, в выражениях, выделяются (по шаблону) нужные биты и при необходимости выполняется сдвиг числа вправо. В результате оно вступает в операцию в соответствии с типом как число со знаком или без него. При ссылке на битовое поле слева от операции присваивания выполняется обратная операция: сдвиг числа влево, выделение по маске нужных битов и размещение их в структурной переменной поразрядной логической операцией с предыдущим содержимым поля.

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

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

Компилятор старается размещать битовые поля в памяти последовательно. Для выравнивания он может свободно переходить к следующему байту или слову.

Манипуляции с битовыми полями являются машинно-зависимыми. Поля могут размещаться как слева направо, так и справа налево (зависит от реализации). В некоторых компьютерах битовые поля могут пересекать границы машинного слова, тогда как в других – нет, но максимальная ширина поля не должна превышать длины слова компьютера. Размещение поля с длиной, не кратной длине слова или байта, возможно с расположением «встык», без пропусков или же с выравниванием на границе. Влиять на размещение битовых полей можно и на уровне синтаксиса языка С++ (в этом случае для выравнивания можно использовать недоступные биты – безымянные поля).

Для структуры с битовыми полями:

struct

{int a:10;

int b:14;

} xx;

представление в памяти переменной хх, в зависимости от реализации может иметь вид:

при выравнивании на границе слова или байта:

7 0 7 0 7 0 7 0

z z z z z z z z z z z z z z ww wwwwwwww

хх.b (14 битов) хх.a (10 битов)

при плотной упаковке:

7 0 7 0 7 0 7 0

  z z z z z z z z z z z z z z ww wwwwwwww

хх.b (14 битов) хх.a (10 битов)


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: