The problem is that both percent and percent are silently encouraged by whole stocks for input of type "int". Thus, multiplication is performed on the signed type.
Misra compatible code - either rewrite code as
uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;
or do as MISRA suggests, immediately cast the result of the expression to its "base type":
uint16_t basic_units = (uint8_t)(rate * percentage);
EDIT: clarification follows.
ISO 9899: 1999 6.3.1.1 2
If int can represent all values โโof the original type, the value is converted to int; otherwise, it is converted to unsigned int. They are called stock integers.
Information text from MISRA-C:
MISRA-C: 2004 6.10.3 Conversion of hazardous types:
/ - /
- Signature change in arithmetic operations: Integral advancement often leads to two unsigned operands giving a result of type (signed) int. For example, adding two 16-bit unsigned operands will give a 32-bit result if int is 32 bits, but an unsigned 16-bit result if int is 16 bits.
Actually, Iโm not sure if the second line will satisfy my MISRA or not, but on the other hand, I may have confused MISRA 10.1 with 10.5 when the latter forces the immediate cast to the base type, but only in case of some bitwise operators.
I tested both lines with the analysis of static LDRA code and did not complain (but gives some incorrect, unrelated warnings), but then LDRA also works very poorly on MISRA-C.
In any case, the problem in the original question is that speed and percentage are implicitly converted by entire proposal packages for the int type, which is signed, since int can represent all uint8_t values. So he becomes
uint16_t basic units = (int)rate * (int)percentage.
To prevent this, you must explicitly specify the type. After thinking, I will go with the first line of my two.