Битовые поля в структурах. Примеры
Содержание
- 1. Битовые поля. Общие понятия. Синтаксис
- 2. Пример использования битовых полей в структуре Date, описывающей дату дня и номер дня в неделе
- 3. Пример сравнения структуры с битовыми полями со структурой, не использующей битовые поля. Структура Time
- Связанные темы
Поиск на других ресурсах:
1. Битовые поля. Общие понятия. Синтаксис
Структуры позволяют удобно группировать данные (переменные) по некоторым критериям. В памяти такие данные, как правило, размещаются друг за другом согласно объявлению.
В языке C++ существует средство сжатия размера памяти, выделяемого под объявленные в структуре переменные. Это битовые поля в структурах.
Битовые поля используются для хранения данных целых типов. При использовании битовых полей в размере типа для них выделяется строго определенное количество бит.
Бывают случаи, когда для хранения данных размер памяти, который для них выделен, слишком большой. Например, чтобы хранить данные о дне недели, размера 1 байта или 8 бит слишком много. Существует 7 дней недели, поэтому достаточно 3 бита для представления этих данных (2 в степени 3 = 8 значений).
Объявление битового поля в структуре выглядит следующим образом
unsigned int field : value;
здесь
- field – имя поля (переменной) в структуре;
- value – количество біт, выделяемых для представления множества значений битового поля.
В свою очередь, объявление структуры, содержащей битовые поля выглядит примерно так:
struct StructName { unsigned int field_1 : value_1; unsigned int field_2 : value_2; ... unsigned int field_N : value_N };
здесь
- StructName – имя структуры;
- field_1, field_2, field_N – названия переменных, которые соответствуют битовым полям структуры;
- value_1, value_2, value_N – целочисленные значения, представляющие собой количество выделенных бит под размеры соответственно полей field_1, field_2, field_N.
В качестве битовых полей рекомендуется использовать тип unsigned int. Это не приведет к искажению результата в случае, когда первый бит будет установлен в 1, что будет означать отрицательное число. Однако, при использовании других целочисленных типов, компилятор не будет выдавать ошибки.
Если в структуре объявить только одно битовое поле, это не даст никакого эффекта. Данные в памяти все равно будут храниться в виде, кратном 8 битам или 1 байту (выравнивание). Польза от битовых полей увеличивается, когда в структуре сохраняется большое количество целочисленных данных. При большом количестве битовых полей можно сэкономить значительное количество байт под один и тот же набор данных без их потери. В свою очередь, использование массивов структур с битовыми полями позволяет существенно уменьшить размер хранимых данных и ускорить выполнение команд обработки этих данных.
⇑
2. Пример использования битовых полей в структуре Date, описывающей дату дня и номер дня в неделе
В задаче объявляется структура Day, описывающая следующие данные о дне:
- номер дня в неделе от 1 до 7. Здесь 1 это понедельник, 2 – вторник и т.д., 7 – воскресенье;
- число в месяце – 1..31;
- номер месяца – 1..12;
- год. Диапазон от 0 до 3000 года.
Для представления дня недели достаточно 3 бита, поскольку 3 бита позволяют получить 8 значений (2^3 = 8). То есть, 8 значений покрывают 7 значений, которые требуются для сохранения номера дня недели.
Исходя из вышеприведенных рассуждений о дне недели, можно сформировать количество бит для других полей структуры Day:
- число в месяце достаточно представить 5 битами (2^5 = 32, 32>31);
- номер месяца достаточно представить 4 битами (2^4 = 16, 16>12);
- для сохранения года достаточно 12 бит (2^12 = 4096, 4096>3000).
Текст демонстрационной программы следующий
#include <iostream> using namespace std; struct Day { unsigned int weekDay : 3; // день недели 1..7 unsigned int number : 5; // число 1..31 unsigned int month : 4; // номер месяца 1..12 unsigned int year : 12; // год 0..3000 }; void main() { // Поля битов в структурах // 1. Объявить структуру Day d; // 2. Заполнить структуру данными 14.01.2022, пятница d.weekDay = 5; d.number = 14; d.month = 1; d.year = 2022; // 3. Вывести данные cout << "d.weekDay = " << d.weekDay << endl; cout << "d.number = " << d.number << endl; cout << "d.month = " << d.month << endl; cout << "d.year = " << d.year << endl; // 4. Вывести размер структуры cout << "sizeof(Day) = " << sizeof(d) << endl; // 4 байти }
Результат выполнения программы
d.weekDay = 5 d.number = 14 d.month = 1 d.year = 2022 sizeof(Day) = 4
⇑
3. Пример сравнения структуры с битовыми полями со структурой, не использующей битовые поля. Структура Time
Пусть нужно реализовать структуру Time, описывающую временной интервал в виде
hours : minutes : seconds : milliseconds
здесь
- hours – количество часов в одних сутках 0..23;
- minutes – количество минут в часе 0..59;
- seconds – количество секунд в минуте 0..59;
- milliseconds – количество миллисекунд 0..999.
Лучше всего для описания подобных данных в структуре используются поля битов. Исходя из максимально допустимых значений, для разных временных интервалов можно выделить разное количество бит в их представлении в структурах:
- поле hours – 5 бит (2^5 = 32 > 23). Из 5 битов можно сформировать до 2^5=32 разных значений, что вполне достаточно для представления 24 значений этого поля;
- minutes – 6 бит (2^6 = 64 > 59);
- seconds – 6 бит (2^6 = 64 > 59);
- milliseconds – 10 бит (2^10 = 1024 > 999).
В программе, с целью демонстрации, создаются две структуры Time и Time2, в которых реализованы необходимые поля для представления времени. Однако структура Time использует битовые поля, а структура Time2 использует обычные значения типа unsigned int.
Текст программы следующий
#include <iostream> using namespace std; // Структура Time использует битовые поля struct Time { unsigned int hours : 5; unsigned int minutes : 6; unsigned int seconds : 6; unsigned int milliseconds : 10; }; // Структура Time2 не использует поля struct Time2 { unsigned int hours; unsigned int minutes; unsigned int seconds; unsigned int milliseconds; }; void main() { // Сравнение структур с битовыми полями и без них // 1. Объявить переменные Time tm; Time2 tm2; // 2. Использование структур в программе // 2.1. Структура типа Time tm.hours = 12; tm.seconds = 36; tm.milliseconds = 777; tm.minutes = 3; // 2.2. Структура типа Time2 tm2.hours = 20; tm2.seconds = 39; tm2.milliseconds = 555; tm2.minutes = 55; // 3. Определить и вывести размер структур Time, Time2 // с помощью оператора sizeof() size_t sizeTime = sizeof(Time); // 4 size_t sizeTime2 = sizeof(Time2); // 16 cout << "sizeTime = " << sizeTime << endl; cout << "sizeTime2 = " << sizeTime2 << endl; }
Результат выполнения программы
sizeTime = 4 sizeTime2 = 16
Как видно из результата, различий между использованием обычных структур и битовых структур нет (доступ к полям, заполнение данными и т.п.). Однако, размер битовой структуры (переменная tm) в памяти занимает всего-навсего 4 байта по сравнению с размером обычной структуры в 16 байт.
В структуре Time происходит добавление битов в полях. Суммарное количество бит составляет
5 + 6 + 6 + 10 = 27
Если разделить 27 на 8 (количество бит в байте), то получится 3 с избытком. То есть, для представления 27 битов нужно 4 байта чтобы корректно отобразить данные.
⇑
Связанные темы
- Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
- Объединения. Ключевое слово union. Примеры объявления и использования объединений
⇑