1

不能将“float64”转换为不同的基本类型“unsigned16”[MISRA 2012 规则 10.8,必需]

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

我该如何解决这条抛出 pc-lint 便笺的行?

4

2 回答 2

1

MISRA C 有复合表达式的概念,简化意味着如果算术表达式包含子表达式,它就是复合表达式。(有关该术语的正式和完整定义,请参见 MISRA-C:2012 8.10.3。)

复合表达式的结果不能转换为不同的基本类型类别,因此您需要将其分解为几个步骤:

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

(x * MIN) + y部分是可以的,因为y与复合表达式具有相同的基本类型(x * MIN),请参见 10.7。

MISRA 为这条规则给出了两个不同的理由:

  • 据说很多人不了解 C 中用于计算的类型。例如,有些人可能认为这(double)(uint16a + uint16b)意味着加法是在double类型上执行的,这当然是错误的。
  • 对隐式类型提升感到困惑。例如uint16a + uint16b,实际上将在 32 位或更大的计算机上在有符号的 32 位类型上执行。

我不确定我是否同意前者的理由是普遍现象,但后者肯定是。

于 2022-01-20T09:34:36.630 回答
1

规则 10.8 规定

复合表达式的值不应转换为不同的基本类型类别或更广泛的基本类型

提供的理由解释了原因。

要解决违规问题,您需要一个两步方法:

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 */

当然,您需要确保结果符合uint16_t...

是的,您的编译器应该对此进行优化。

于 2022-01-20T07:57:54.223 回答