Предупреждение: «Выражение, являющееся результатом операции ~ или <<, не было приведено к своему основному типу». Как исправить?

Я выполняю операцию с байтами, где хочу добавить uint8 к MSB существующего uint32:

uint32 my_uint32;
my_uint32 = 0x00ffffffu;

my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u));  // Add value 0x02 to the MSB of my_uint32 
my_uint32 = 0x02ffffffu    // This is what I get and is working so far

Это пока нормально, но я получаю предупреждение:

"Выражение, являющееся результатом операции ~ или <<, не было приведено к своему основному типу"

Я могу избавиться от предупреждения, выполнив:

my_uint32 = ((uint32)(my_uint32) | (uint8)((0x2u) << 24u)); // Here I'm doing the uint8 cast on the complete shift operation

Но чем это не сработает. Результат будет:

my_uint32 = 0x00ffffffu

Кто-нибудь знает, как я могу избежать предупреждения?

2<<24 слишком велик для 8 бит, т.е. (uint8)(2<<24) == 0
pmg 15.12.2020 12:00

Я не могу воспроизвести это с uint8_t и uint32_t, так что, может быть, это артефакт ваших (нестандартных?) типов? Используется clang, который обычно довольно сварлив и совершенно холоден, ноль предупреждений.

tadman 15.12.2020 12:07

@tadman: Правильно. Но первое решение точно сработает. Но как избавиться от предупреждения, чем?

JohnDoe 15.12.2020 12:07

Это сообщение от компилятора или от инструмента MISRA? Каков размер int в вашей реализации C?

Eric Postpischil 15.12.2020 12:08

@EricPostpischil: это предупреждение MISRA. Размер int 32 бита,

JohnDoe 15.12.2020 12:09

Почему вы используете такое приведение типов, если результат сразу же преобразуется снова? Почему бы не использовать более подходящий тип?

Gerhardh 15.12.2020 12:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
315
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это должно работать:

my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(uint8)(0x2u) << 24u));

Но можно сократить до этого:

my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(0x2u) << 24u));

Извините, но это не имеет никакого смысла и, конечно же, не требуется для MISRA-C.

Lundin 15.12.2020 16:36

@Lundin Я не совсем знаком с MISRA-C, но предполагая, что uint32 ведет себя как стандарт uint32_t, цель приведения (uint32) к левому операнду << состоит в том, чтобы гарантировать, что смещаемое значение имеет 32 бита значения, а намерение приведения (uint32) к результату операции << должно соответствовать данному предупреждению «Выражение, являющееся результатом операции ~ или <<, не было приведено к его основному типу» (что бы ни означал «основной тип»!) .

Ian Abbott 15.12.2020 17:02

Если мы игнорируем 16-битную int систему, то этот код делает следующее: 2u = дайте мне беззнаковое целое, не ждите, я передумал дайте мне uint8, не ждите, я передумал, дайте мне uint32, как у меня было из start, shift, затем конвертируйте из uint32 в uint32. Все это бессмысленно.

Lundin 16.12.2020 08:14

Предупреждение касается неправильного приведения uint8, которое следует просто удалить. Я опубликовал ответ, объясняющий это.

Lundin 16.12.2020 08:15

@Lundin Думаю, теперь я понял. Предупреждение было выдано из-за того, что результат оператора << не приводился к типу левого операнда <<, который является «основным типом». Приведение к (uint8) послужило бы цели, если бы оно усекало операнд.

Ian Abbott 16.12.2020 11:05
Ответ принят как подходящий

Замените my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u)); на my_uint32 = my_uint32 | ((uint32) 0x2u << 24);.

По существу, левый операнд сдвига должен быть преобразован в желаемый тип результата, чтобы сдвиг выполнялся с этим типом. Приведение его к uint8 приводит к тому, что сдвиг выполняется с типом int из-за автоматического повышения.

Также нет необходимости приводить к uint32, если только система не использует 16-битные целые числа или не должна быть переносима на такие системы. Код уже был совместим с MISRA еще до того, как началось все это преобразование.

Lundin 15.12.2020 16:35

@Lundin: В этом конкретном значении нет необходимости, но в будущем его можно легко изменить на 0x80 или какой-либо макрос, и я подумал, что MISRA и / или OP могут захотеть, чтобы форма выражения была правильной независимо от операнда. сдвинутый.

Eric Postpischil 15.12.2020 16:46

Это означает, что операнд (uint8)(0x2u) неявно повышается до int, который является подписанным. Такие рекламные акции могут вызывать тонкие ошибки.

Некоторые старые рекомендации MISRA заключаются в том, чтобы впоследствии привести к основному типу, чтобы гарантировать, что тип выражения остается согласованным:

(uint32_t)(some_uint8_t << 24)

Тем не менее, я бы лично порекомендовал сделать это приведение явно перед сдвигом, чтобы вы не рисковали продвижением типа до знакового типа, а затем случайными сдвигами, когда вы оставили биты сдвига в бит знака или сдвиг вправо с сохранением знака (арифметический сдвиг) и т.д. То есть сделать так:

(uint32_t)some_uint8_t << 24

Это лучшая практика для всех 32-битных систем.


Однако в вашем конкретном случае проблема здесь: (uint8)(0x2u).

2u уже имеет тип unsigned int, который уже является правильным типом для битового сдвига на 24. (Если это не система с 16-битным int, в этом случае приведение к uint8 также не имеет никакого смысла.)

Просто отбросьте все странные слепки! Этот код соответствует требованиям MISRA-C:

my_uint32 = my_uint32 | (0x2u << 24u);

Вам нужно привести этот операнд только в том случае, если вам нужен код для работы в 16-битных системах, и в этом случае вы можете сделать либо (uint32)0x2u, либо 0x2ul, любой из них подходит и совместим с MISRA.

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