Переполнение битового поля для подписанного перечисления базового типа - PullRequest
0 голосов
/ 28 августа 2018

Это только для C ++ 11:

Если у меня обычное перечисление, как показано ниже:

enum TestType
{
Test0 = 0,
Test1,
Test2,
Test3,
Test4,
Test5,
Test6,
Test7
}

и упакованная структура, подобная этой:

struct
{
TestType a : 3
uint32_t b : 5
} TestStruct;

Гарантируется ли TestStruct.a равным любому действительному назначенному значению перечисления при доступе? Или есть вероятность того, что компилятор назначит базовый тип со знаком и затем обработает битовое поле a как диапазон от -4 до 3.

1 Ответ

0 голосов
/ 28 августа 2018

Гарантируется ли TestStruct.a равным присвоенному ему значению перечисления?

Нет. Вы по умолчанию инициализируете TestStruct. Если это в глобальном пространстве, то оно будет инициализировано нулями, а a и b будут равны 0.

Если это находится в пространстве блока, то инициализация не происходит, что означает, что a и b имеют неопределенное значение. Все, что вы знаете, это то, что значение будет в представимом диапазоне для типа. Test0 со значением 0 здесь вообще не вступает в игру.

Если бы у вас было

TestStruct{};

Тогда a и b будут равны нулю, так как вы инициализируете объект значением, и в этом случае это означает, что вы инициализируете его нулем. Вы также можете использовать

TestStruct{value1, value2};

для присвоения определенных значений a и b.


Что касается вопроса о том, может ли a хранить все значения TestType, нам нужно взглянуть на [class.bit] / 4 , в котором указано

[...] Если значение перечислителя хранится в битовом поле с тем же типом перечисления, а число битов в битовом поле достаточно велико, чтобы содержать все значения этого типа перечисления ([dcl.enum]), исходное значение перечислителя и значение битового поля должны сравниваться равными.

упорная мина

и значения перечисления определяются как [dcl.enum] / 8 как

Для перечисления, базовый тип которого является фиксированным, значения перечисления являются значениями базового типа. В противном случае для перечисления, где e min является наименьшим счетчиком, а e max является наибольшим, значения перечисления являются значениями в диапазоне от b min до b max , определяемых следующим образом: Пусть K будет 1 для представления дополнения до двух и 0 для представления дополнения или величины единицы. b max - наименьшее значение, большее или равное max (| e min - K, | e max |) и равное 2 M -1, где M - неотрицательное целое число. b min равно нулю, если e min неотрицательно и - (b max + K) в противном случае. Размер самого маленького битового поля, достаточного для хранения всех значений типа перечисления, равен max (M, 1), если b min равно нулю, а M + 1 в противном случае. Можно определить перечисление, значения которого не определены ни одним из перечислителей. Если перечислитель-список пуст, значения перечисления такие, как если бы перечисление имело единственный перечислитель со значением 0

Таким образом, в этом случае e min равно 0 и e max 7, поэтому b min равно 0 и b max равно или больше, чем max (| e min | - K, | e max |), что равно 7. Так как оно должно быть равно 2 M −1 если мы используем 3 для M, то мы также получаем 7.

У нас есть

Размер наименьшего битового поля, достаточного для хранения всех значений типа перечисления, равен max (M, 1), если b min равно нулю, а M + 1 в противном случае.

и b min равно нулю, поэтому наименьшее необходимое нам битовое поле равно 3, которое у вас есть, поэтому вы гарантированно поместите все значения TestType в a.

...