2016-03-18 10 views
0

Say У меня есть битовый вроде этого:Портативный способ назначить максимальное значение в битовое поле

struct SomeStruct { 
    uint32_t first : 12; 
    uint32_t second : 2; 
    uint32_t third : 18; 
}; 

SomeStruct obj; 

Я хочу, чтобы назначить

obj.second = 3; // Actually, the maximum allowed value 

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

Мой код используется

obj.second = std::numeric_limits<uint32_t>::max() 

но лязг с -Wbitfield-constant-conversion выдает предупреждение об этом и cpp reference states:

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

Значит, назначает -1 или numeric_limits<uint32_t>::max() действительно переносным или есть ли другой способ?

+0

связанный/обман: http://stackoverflow.com/questions/3319717/is-there-a-bit-equivalent-of-sizeof-in-c и http://stackoverflow.com/questions/539251/getting -the-size-of-an-indiviual-field-from-ac-struct-field – NathanOliver

+0

@NathanOliver, так вы подразумеваете, что ответ на мой вопрос «это невозможно?». – unkulunkulu

+0

Ну, если вы хотите получить размер в битах, чтобы вычислить max, тогда да. Это зависит от того, что вы хотите сделать. Вот почему я пошел со связанными в первую очередь. – NathanOliver

ответ

2

Если у вас есть два бита, максимальное значение равно 2 -1. Один простой способ получить это значение является сдвигом 1 два шага влево (давая вам 2) и вычитая 1.

Таким образом, максимальное значение для 2 битов (1U << 2) - 1.

Он переносится между всеми компиляторами C, и компилятор сможет оптимизировать операцию, поэтому назначение предназначено только для результирующего значения.

+0

ok, переносимый true, но я хочу, чтобы это назначение было стабильным и работало, если ширина битового поля изменится. Я добавлю это на вопрос – unkulunkulu

0

Для беззнаковых целых типов:

unsigned char max = ~0; 

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

Поскольку вы используете битполы, этот простой подход может не сработать для вас. Если вы использовали:

struct SomeStruct { 
    uint8_t first; 
    uint8_t second; 
    uint8_t third; 
}; 

Тогда это может быть вариант.

+0

, нам нужно инициализировать некоторые битовые поля, а не unsigned char –

2

Поскольку поля без знака, работа проста:

obj.second = -1; 

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

+0

. Это оптимальный ответ. –

+0

Не могли бы вы подробнее рассказать о ссылке на стандартный/другой достоверный источник, поскольку мне удалось найти этот http: //en.cppreference.com/w/cpp/language/bit_field и там указано, что следующие свойства битовых полей определены реализацией Значение, которое возникает при присвоении или инициализации битового поля значением вне диапазона, или от приращения битного поля за пределы его диапазона. ' – unkulunkulu

+0

@unkulunkulu Я не вижу никакого текста в стандарте C++, соответствующего этой цитате. В разделе бит-полей нет ничего, что делает исключение для их поведения при преобразовании вне диапазона. поэтому я думаю, что применяется [conv.integral], что является одним и тем же поведением для других целочисленных типов: преобразование вне диапазона в неподписанные обертывания, а преобразование вне диапазона для подписания - это реализация. –

0

Лучший путь присвоив -1/-1L/~0/~0L или INT_MAX/LONG_MAX.

Но этот код основан на том, как целые числа представлены на современных компьютерах. Это работает повсеместно, но формально из стандартной спецификации C не переносится.

+0

'~ 0' полагается на представление дополнений 2 –

+0

@ M.M: Это правильно. Но при назначении числа меньшему типу, стандарт C говорит, что он использует modulo. Другими словами, если число не было равно 2, это привело бы к некоторому странному числу. Хотя все текущее программное обеспечение полагается на это довольно много ... –