表达式分配给更广泛的基本类型

hom*_*own 5 c lint misra

我从分析工具中收到以下警告,Composite expression assigned to a wider essential type 这是代码:

uint32_t result;
uint8_t resolution;

result = 1U << resolution;
Run Code Online (Sandbox Code Playgroud)

我尝试了以下方法:

#define SHIFT_BY_ONE (uint8_t)1
result  = SHIFT_BY_ONE << resolution;
Run Code Online (Sandbox Code Playgroud)

但这会引发此警告,Shift left of signed quantity (int) 所以我想我无法正确理解该问题。如何解决此错误?

Lun*_*din 7

听起来好像您正在运行MISRA-C:2012检查器。基本类型复合表达式是MISRA-C的术语,而不是C标准的术语。

为了完全理解此警告,您必须研究基本类型(MISRA-C:2012 8.10)和复合表达式(MISRA-C:2012 8.10.3)的含义。

至于警告的原因,是规则10.6:

复合表达式的值不得分配给具有较宽本质类型的对象。

如果我们忽略所有这些术语的含义,那么规则归结为,如果您有一个带有2个较小类型的操作数的运算,那么结果不应分配给比那些操作数更大的变量。

这是为了防止这样的代码:

uint16_t a = 40000;
uint16_t b = 40000;
uint32_t result = a + b;
Run Code Online (Sandbox Code Playgroud)

在16位系统上,操作数ab不会被提升,因此实际操作将在16位类型上执行-并且将发生无符号回绕(或在有符号变量的情况下溢出)。

困惑的程序员不了解C中隐式类型提升的工作方式,他们可能会认为执行上述操作uint32_t只是因为结果存储在这种类型中。但这是不正确的,赋值运算符的左侧与子表达式无关a + b。在子表达式中使用哪种类型完全由运算符优先级决定,并且=优先级低于+

显然,MISRA-C认为这种误解是普遍的,这就是该规则的理由。

至于如何解决,很容易:

result = (uint32_t)1U << resolution;
Run Code Online (Sandbox Code Playgroud)