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 ondouble
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.