2011-06-15 6 views
4

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

Нелегальное неявное преобразование из базового типа МИСРА «неподписанного символа» с «без знака Int» в комплексном выражении (МИСР С 2004 Правилом 10,1)

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

ответ

4

Проблема заключается в том, что как скорость и процент молчаливо способствует целочисленные поощрений к типу «ИНТ». Таким образом, умножение выполняется на подписанном типе.

МИСРА код совместит либо переписать код, как

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

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

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

EDIT : Далее следует разъяснение.

ИСО 9899: 1999 6.3.1.1 2

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

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

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

/-/

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

Я на самом деле не знает, выше ли вторая линия шахты будет удовлетворять MISRA или нет, на второй мысли я могу спутал MISRA 10,1 с 10,5, где последний обеспечивает соблюдение немедленного приведения к базовому типу, но только в случае определенных поразрядных операторов.

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

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

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

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

+0

Вы хотите перевести на: uint16_t' во 2 строчке, да? – pmg

+0

Почему продвижение двух неподписанных типов 'uint8_t' приводит к подписанному типу' int', а не к более большому неподписанному типу 'unsigned int' или более просто' uint16_t'? – Ioan

+0

@pmg Я думаю, что я фактически перепутал правила 10.1 и 10.5 MISRA. Если бы это были ~ или << операторы, которые я бы заставил MISRA привести к типу в «базовый тип». Я редактировал свой пост, чтобы прояснить ситуацию. – Lundin

2

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

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

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

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

К сожалению, я почти что-то написал. Хотя обратите внимание, что MISRA недовольна использованием unsigned (int) в консультативных правилах, поэтому вы должны прибегать к методу uint16_t для максимального закрытия инструмента. – Lundin

+0

Хм, у меня нет правил MISRA :) Я просто подумал, что когда 'uint16_t' имеет меньший ранг, чем' int', проблема не исчезнет: значения будут преобразованы в более крупный тип 'unsigned 'тоже тоже. – pmg

+0

Действительно, если uint16_t окажется неподписанным, это все равно будет продвигаться. Возможно, лучший (и самый MISRA-совместимый) код, таким образом, приведет к получению результата, как и во второй строке кода в моем ответе. – Lundin

1

Правило 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 пытается сделать код более безопасным независимо от размера типов на целевой платформе.