Как устранить ошибку конверсии при использовании битовых полей?

Есть такая структура:
typedef struct {
uint32_t flags : 12;
uint32_t addr : 20; // Верхние 20 бит адреса
} some_type_t;

void set_addr(some_type_t* sv, uint32_t addr)
{
    sv->addr = addr >> 12;
}


В итоге GCC выдаёт такую ошибку:
error: conversion from 'uint32_t' {aka 'long unsigned int'} to 'unsigned int:20' may change value [-Werror=conversion]
   31 |     sv->addr = addr >> 12;
      |                             ^~~~~~~~~~


Решилось всё таким вариантом:
uint32_t addr_shifted = addr >> 12;
sv->addr = addr_shifted & 0xFFFFFu;

0xFFFFF это маска для 20 нижних бит.
Она вроде как говорит компилятору, что верхние 12 бит нас не интересуют.

Но что более забавно, такой код не работает:
sv->addr = (addr >> 12) & 0xFFFFFu;
Почему?
  • Вопрос задан
  • 804 просмотра
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Как устранить ошибку конверсии при использовании битовых полей?

Не использовать битовые поля. Серьёзно. Удобств на копейку а мороки на рубль.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
AshBlade
@AshBlade
Просто хочу быть счастливым
Я протестировал это (со встроенным (addr >> 12) * 0xFFFFu) у себя на GCC (версия 11.4.0) и clang (14.0.0) на x86_64. Дополнительно в нескольких онлайн компиляторах. И на MinGW (версия 6.3.0).
Нигде предупреждений подобных не встречал.
Скорее всего это особенность версии компилятора/платформы.
Ответ написан
@res2001
Developer, ex-admin
У вас ошибка появляется из-за опции -Werror=conversion компилятора. Она заставляет компилятор генерировать ошибки при любом неявном преобразовании, в котором есть вероятность потери данных или изменении значения. А в этой операции такая вероятность есть по формальным признакам.
Тут можно либо убрать опцию, либо, применить явное преобразование к unsigned int:20

Согласен с jcmvbkbc по поводу отказа от битовых полей.
Хотя опция -Werror=conversion добавит проблем и без битовых полей, но, с другой стороны, она заставляет глубже понимать, то что вы написали.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы