Что такое синтаксис структуры C ++ & # 8220; a: b & # 8221; имею в виду

StackOverflow https://stackoverflow.com/questions/824295

Вопрос

Если у меня есть структура C ++, определение 64-битного слова данных, например ..

struct SMyDataWord
{
    int Name : 40;
    int Colour : 24;
};

Что означает синтаксис : 40 ... означает ли это, что первые 40 бит зарезервированы для имени, а оставшиеся 24 бита для цвета?

Вот как это выглядит, но я не сталкивался с этим раньше.

Это было полезно?

Решение

Битовые поля, перенесенные из C. Name имеет ширину 40 бит, Color имеет ширину 24 бита. Следовательно, ваша структура имеет как минимум 64 бита. В моей системе 64 бита были бы 8 байтами.

Другие советы

Это определение битового поля.

Имя - это целое число, которое может хранить ровно 40 бит информации. Цвет может хранить 24 бита.

Это часто делается для того, чтобы сэкономить место в часто используемых структурах или сжать код до размера, который легко обрабатывать для ЦП (в вашем случае 64 бита. Вписывается точно в регистр ЦП на 64-битной машине).

Код, который обращается к битовым полям, будет выполняться чуть медленнее.

Используйте их разумно :

  

Помните, что почти все о   битовые поля - это реализация   зависимый. Например, биты ли   хранятся слева направо или   справа налево зависит от фактического   аппаратная архитектура. Более того,   каждый компилятор использует свой член   модель выравнивания, поэтому размер   оптимизированного BillingRec 12   байтов, а не 9. Вы не можете взять   адрес битового поля, вы не можете создать   массивы битов. Наконец, на большинстве   реализации использования битовых полей   несет на себе скорость над головой. Поэтому, когда   Вы оптимизируете свой код, измеряете   эффект определенной оптимизации и   его компромиссы, прежде чем вы решите использовать   он.

Здесь sizeof прекрасно демонстрирует, что происходит под капотом:

#include <iostream>
#include <climits>

struct bc_1 {
   int a : 1;
   int b : 1;
};

struct bc_2 {
   int a : 31;
   int b : 1;
};

struct bc_3 {
   int a : 32;
   int b : 1;
};

struct bc_4 {
   int a : 31;
   int b : 2;
};

struct bc_5 {
   int a : 32;
   int b : 32;
};

struct bc_6 {
   int a : 40;
   int b : 32;
};

struct bc_7 {
   int a : 63;
   int b : 1;
};

int main(int argc, char * argv[]) {
    std::cout << "CHAR_BIT = " << CHAR_BIT;
    std::cout << " => sizeof(int) = " << sizeof(int) << std::endl;

    std::cout << "1,  1:  " << sizeof(struct bc_1) << std::endl;
    std::cout << "31, 1:  " << sizeof(struct bc_2) << std::endl;
    std::cout << "32, 1:  " << sizeof(struct bc_3) << std::endl;
    std::cout << "31, 2:  " << sizeof(struct bc_4) << std::endl;
    std::cout << "32, 32: " << sizeof(struct bc_5) << std::endl;
    std::cout << "40, 32: " << sizeof(struct bc_6) << std::endl;
    std::cout << "63, 1:  " << sizeof(struct bc_7) << std::endl;
}

Дальнейшие действия зависят от вашего компилятора и ОС, и, возможно, от вашего оборудования. В macOS с gcc-7 (с CHAR_BIT = 8 32-битный int (т.е. половина 64-битного long ) имеет sizeof (int) = 4) это вывод, который я вижу:

CHAR_BIT = 8 => sizeof(int) = 4
1,  1:  4
31, 1:  4
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 12
63, 1:  8

Это говорит нам о нескольких вещах: если оба поля типа int помещаются в один int (т. е. 32 бита в примере выше), компилятор выделяет только один Объем памяти int ( bc_1 и bc_2 ). Как только один int больше не может содержать битовые поля, мы добавляем второе ( bc_3 и bc_4 ). Обратите внимание, что bc_5 заполнен.

Интересно, что мы можем " выбрать " больше битов, чем позволено. Смотрите bc_6 . Здесь g ++ - 7 выдает предупреждение:

bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type
     int a : 40;
             ^~

Обратите внимание: clang ++ объясняет это более подробно

bitfields.cpp:30:9: warning: width of bit-field 'a' (40 bits) exceeds the width of its type; value will be truncated to 32 bits [-Wbitfield-width]
    int a : 40;
    ^

Однако кажется, что под капотом компилятор выделяет другой объем памяти int . Или, по крайней мере, он определяет правильный размер. Я предполагаю, что компилятор предупреждает нас, чтобы мы не обращались к этой памяти как int a = bc_6 :: a (я бы поспорил, что int a будет иметь только первые 32 бита поле bc_6 :: a ...). Это подтверждается bc_7 , общий размер которого равен двум int , но первое поле охватывает большинство из них.

Наконец, замена int на long в приведенном выше примере ведет себя как ожидалось:

CHAR_BIT = 8 => sizeof(long) = 8
1,  1:  8
31, 1:  8
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 16
63, 1:  8
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top