Что такое синтаксис структуры C ++ & # 8220; a: b & # 8221; имею в виду
-
05-07-2019 - |
Вопрос
Если у меня есть структура 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