Why did my tool throw a misra error here?

What can I do to avoid the MISRA error for this code below? I tried casting with (unit16_t). But then this did not allow an explicit conversion.

Unalloyed implicit conversion from the MISRA base type "unsigned char" to "unsigned int" in a complex expression (rule 10 of MISRA C 2004)

  uint8_t rate = 3U; 
  uint8_t percentage = 130U;      
  uint16_t basic_units = rate * percentage;
+5
c misra
source share
4 answers

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.

+5
source share

A direct conversion is performed before multiplication for multiplication. Perhaps explicit conversion just before multiplication closes your tool

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

The resulting unsigned value must be implicitly converted to uint16_t without warning. If your tool also selects PITA, try another explicit conversion:

 uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage); 
+2
source share

The MISRA rule attempts to ensure that the "base type" used for computation is the same as the resulting type. For this you can use one or both of the operands:

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

In a 32-bit architecture, the result without translation is fine, however, consider the following:

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

In a 32-bit architecture, the operation will be performed in 32 bits - even if the target type is 64 bits wide. Where the speed and percentage are large enough, this can lead to a 32-bit operation wrapping and, therefore, data that will correspond to the target type will be lost.

The MISRA rule attempts to make code more secure regardless of the type size on the target platform.

+1
source share

If you try to distinguish your operands with C-style casting, you can just give your tool something else to complain about. So instead:

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

You may need the following:

 uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage); 
0
source share

All Articles