Поиск…


Вступление

Бит-поля плотно упаковывают структуры C и C ++ для уменьшения размера. Это кажется безболезненным: укажите количество бит для членов, а компилятор выполняет работу со-смешивающих битов. Ограничением является невозможность принять адрес члена битового поля, поскольку он хранится совместно. sizeof() также не разрешено.

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

замечания

Насколько дороги побитовые операции? Предположим, что простая небитовая структура поля:

struct foo {
    unsigned x;
    unsigned y;
}
static struct foo my_var;

В более позднем коде:

my_var.y = 5;

Если sizeof (unsigned) == 4 , то x сохраняется в начале структуры, а y хранится в 4 байта. Сгенерированный код сборки может напоминать:

loada register1,#myvar     ; get the address of the structure
storei register1[4],#0x05  ; put the value '5' at offset 4, e.g., set y=5

Это просто, потому что х не смешивается с y. Но представьте себе переопределение структуры с битовыми полями:

struct foo {
    unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
    unsigned y : 4;
}

И x и y будут выделены 4 бита, разделяя один байт. Таким образом, структура занимает 1 байт, а не 8. Рассмотрим сборку, чтобы установить y теперь, предполагая, что она заканчивается в верхнем полубайте:

loada  register1,#myvar        ; get the address of the structure
loadb  register2,register1[0]  ; get the byte from memory
andb   register2,#0x0f         ; zero out y in the byte, leaving x alone
orb    register2,#0x50         ; put the 5 into the 'y' portion of the byte
stb    register1[0],register2  ; put the modified byte back into memory

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

Использование драйвера устройства: избегайте бит-полей как умной стратегии реализации драйверов устройств. Битовые поля хранения не обязательно согласованы между компиляторами, что делает такие реализации не переносимыми. Значение read-modify-write для установки значений может не делать то, что ожидают устройства, вызывая неожиданное поведение.

Декларация и использование

struct FileAttributes
{
    unsigned int ReadOnly: 1;    
    unsigned int Hidden: 1;
};

Здесь каждое из этих двух полей будет занимать 1 бит в памяти. Он определяется выражением : 1 после имен переменных. Базовый тип битового поля может быть любым интегральным типом (8-битный int до 64-битного int). Рекомендуется использовать unsigned тип, иначе могут возникнуть сюрпризы.

Если требуется больше бит, замените «1» на количество бит. Например:

struct Date
{
    unsigned int Year : 13; // 2^13 = 8192, enough for "year" representation for long time
    unsigned int Month: 4;  // 2^4 = 16, enough to represent 1-12 month values.
    unsigned int Day:   5;  // 32
};

Вся структура использует всего 22 бита, и с обычными настройками компилятора sizeof этой структуры будет 4 байта.

Использование довольно простое. Просто объявите переменную и используйте ее как обычную структуру.

Date d;

d.Year = 2016;
d.Month = 7;
d.Day =  22;

std::cout << "Year:" << d.Year << std::endl <<
        "Month:" << d.Month << std::endl <<
        "Day:" << d.Day << std::endl;


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow