Почему мой инструмент выдает здесь ошибку MISRA? - PullRequest
5 голосов
/ 15 июня 2011

Что я могу сделать, чтобы MISRA не выдавала эту ошибку для кода ниже? Я пробовал кастовать с (unit16_t). Но тогда это не позволило явное преобразование.

Незаконное неявное преобразование из базового типа MISRA "unsigned char" в "unsigned int" в сложном выражении (MISRA C 2004, правило 10.1)

 uint8_t rate = 3U; 
 uint8_t percentage = 130U;      
 uint16_t basic_units = rate * percentage;

Ответы [ 4 ]

5 голосов
/ 15 июня 2011

Проблема в том, что целочисленные продвижения молча переводят как процент, так и процент в тип "int".Следовательно, умножение выполняется для типа со знаком.

Код, совместимый с MISRA, должен либо переписать код как

 uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

, либо сделать так, как предлагает MISRA, немедленно типизировать результат выражения в его«базовый тип»:

 uint16_t basic_units = (uint8_t)(rate * percentage);

РЕДАКТИРОВАТЬ: разъяснение следует.

ISO 9899: 1999 6.3.1.1 2

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

Информационный текст от MISRA-C:

MISRA-C: 2004 6.10.3 Преобразования опасных типов:

/ - /

- Изменение подписи в арифметических операциях: Интегральное продвижение часто приводит к двум беззнаковым операндам, приводящим к результату типа (подпись)INT .Например, добавление двух 16-разрядных операндов без знака даст 32-разрядный результат со знаком, если int составляет 32 бита, но 16-разрядный результат без знака, если int - 16 бит.

На самом деле я не уверен, удовлетворяет ли MISRA 2-я строка выше, если подумать, возможно, я перепутал MISRA 10.1 с 10.5, где последний обеспечивает немедленное приведение к базовому типу., но только в случае некоторых побитовых операторов.

Я протестировал обе строки с помощью статического анализа кода LDRA, и он не жаловался (но выдает несколько неправильных, не связанных предупреждений), но затем LDRA также работает очень плохов MISRA-C.

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

uint16_t basic units = (int)rate * (int)percentage.

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

2 голосов
/ 15 июня 2011

Неявное преобразование выполняется перед умножением для умножения.Возможно, явное преобразование прямо перед умножением закрывает ваш инструмент

uint16_t basic_units = (unsigned)rate * (unsigned)percentage;

Полученное значение unsigned должно быть неявно преобразовано в uint16_t без предупреждений.Если ваш инструмент тоже выбирает PITA, попробуйте другое явное преобразование:

uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage);
1 голос
/ 09 февраля 2012

Правило MISRA пытается убедиться, что «базовый тип», используемый для расчета, совпадает с результирующим типом.Чтобы добиться этого, вы можете привести один или оба операнда:

uint8_t rate = 3U; 
uint8_t percentage = 130U;      
uint16_t basic_units = (uint16_t)rate * percentage;

В 32-разрядной архитектуре результат без преобразования в порядке, однако следует учитывать следующее:

uint32_t rate =  ...;
uint32_t percentage = ...;
uint64_t basic_units = rate * percentage;

В 32-битной архитектуре операция будет выполняться в 32 битах, даже если целевой тип имеет 64-битную ширину.Если процент и процент достаточно велики, это может привести к переносу операции в 32 бита, и поэтому данные, которые будут соответствовать целевому типу, будут потеряны.

Правило MISRA пытается сделать код более безопасным независимо отразмера типов на целевой платформе.

0 голосов
/ 29 марта 2018

Если вы попытаетесь привести свои операнды с использованием преобразования в стиле C, вы можете просто дать своему инструменту что-то еще, на что можно пожаловаться.Таким образом, вместо этого:

uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

Возможно, вам понадобится сделать это:

uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...