Проблема заключается в том, что как ставка, так и процент молча продвигаются целочисленными акциями до типа «int». Таким образом, умножение выполняется над типом со знаком.
Код, совместимый с MISRA, должен либо переписать код как
uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;
или сделайте, как предлагает MISRA, немедленно приведите результат выражения к его «базовому типу»:
uint16_t basic_units = (uint8_t)(rate * percentage);
EDIT: следует пояснение.
ИСО 9899:1999 6.3.1.1 2
Если int может представлять все значения исходного типа, значение преобразуется в int; в противном случае он преобразуется в беззнаковое целое число. Они называются целочисленными акциями.
Информативный текст от MISRA-C:
MISRA-C:2004 6.10.3 Опасные преобразования типов:
/--/
– Изменение знака в арифметических операциях: целочисленное преобразование часто приводит к тому, что два операнда без знака дают результат типа (signed) 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.
Чтобы предотвратить это, вы должны явно указать тип. Подумав еще раз, я бы выбрал 1-ю строку из двух вышеперечисленных.
person
Lundin
schedule
15.06.2011