cannot cast 'float64' to different essential type 'unsigned16' [MISRA 2012 Rule 10.8, required]

cannot cast 'float64' to different essential type 'unsigned16' [MISRA 2012 Rule 10.8, required]

double x, y;
#define MIN 2.0
uint16_t z = (uint16_t) ((x * MIN) + y);

How can I resolve this line throwing pc-lint note?


MISRA C has the concept of composite expressions which simplified means that if an arithmetic expression contains sub-expressions, it is a composite expression. (For the formal and complete definition of the term see MISRA-C:2012 8.10.3.)

The result of a composite expression can't be cast to a different essential type category, so you need to break it down in several steps:

double tmp = (x * MIN) + y; 
uint16_t z = (uint16_t)tmp; // OK: tmp is not a composite expression

The (x * MIN) + y part is OK because y is of same essential type as the composite expression (x * MIN), see 10.7.

MISRA gives two different rationales for this rule:

  • A lot of people supposedly don't grasp which type that is used for a calculation in C. For example some might believe that (double)(uint16a + uint16b) means that the addition is carried out on double type, which is of course wrong.
  • Confusion about implicit type promotions. For example uint16a + uint16b will actually get carried out on a signed 32 bit type on a 32 bit or larger computer.

I'm not sure if I agree that the former rationale is a common phenomenon, but the latter surely is.


Rule 10.8 states

The value of a composite expression shall not be cast to a different essential type category or a wider essential type.

The Rationale provided explains why.

To resolve the violation, you need a two step approach:

double x, y;
#define MIN 2.0

double   w = (x * MIN) + y; /* Composite expression, in double */
uint16_t z = (uint16_t)w;   /* Explicit conversion to uint16_t */

Of course, you'll need to be sure that the result fits in uint16_t...

And yes, your compiler should optimize this.