Что означает двоеточие в объявлении структуры, например:1,:7,:16 или:32?

Что означает следующий код C++?

unsigned char a : 1; 
unsigned char b : 7;

Я предполагаю, что это создает два символа a и b, и оба они должны быть длиной в один байт, но я понятия не имею, что делают части ": 1" и ": 7".

3 ответа

Решение

1 и 7 - это размеры битов, ограничивающие диапазон значений. Они обычно встречаются в структурах и союзах. Например, в некоторых системах (зависит от char ширина и правила упаковки и т. д.), код:

typedef struct {
    unsigned char a : 1;
    unsigned char b : 7;
} tOneAndSevenBits;

создает 8-битное значение, один бит для a и 7 бит для b,

Обычно используется в C для доступа к "сжатым" значениям, таким как 4-битный nybble, который может содержаться в верхней половине 8-битного символа:

typedef struct {
    unsigned char leftFour  : 4;
    unsigned char rightFour : 4;
} tTwoNybbles;

Для языковых юристов среди нас раздел 9.6 стандарта C++11 объясняет это подробно, слегка перефразируя:


Битовые поля [class.bit]

Член-декларатор формы

идентификаторopt атрибут-спецификаторopt: константа-выражение

указывает битовое поле; его длина выделяется из имени битового поля двоеточием. Необязательный атрибут-спецификатор относится к объявляемой сущности. Атрибут битового поля не является частью типа члена класса.

Выражение константы должно быть интегральным выражением константы со значением, большим или равным нулю. Значение выражения интегральной константы может быть больше, чем число битов в объектном представлении типа битового поля; в таких случаях дополнительные биты используются в качестве битов заполнения и не участвуют в представлении значения битового поля.

Распределение битовых полей внутри объекта класса определяется реализацией. Выравнивание битовых полей определяется реализацией. Битовые поля упакованы в некоторый адресуемый блок выделения.

Примечание: битовые поля расположены на одних машинах, а не на других. Битовые поля назначаются справа налево на некоторых машинах, слева направо на других. - конец примечания

Я верю, что это будут битовые поля.

Строго говоря, битовое поле должно быть int, unsigned int или _Bool. Хотя большинство компиляторов будут принимать любые целочисленные типы.

Ссылка C11 6.7.2.1:

Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, со знаком int, без знака int или каким-либо другим типом, определяемым реализацией.

Ваш компилятор, вероятно, выделит 1 байт памяти, но он может получить больше.

Ссылка C11 6.7.2.1:

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

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

Ссылка C11 6.7.2.1:

Если остается достаточно места, битовое поле, которое непосредственно следует за другим битовым полем в структуре, должно быть упаковано в смежные биты той же единицы. Если остается недостаточно места, определяется, будет ли битовое поле, которое не помещается, в следующий блок или перекрывает соседние блоки, определяется реализацией.

Другие вопросы по тегам