我从分析工具中收到以下警告,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)
所以我想我无法正确理解该问题。如何解决此错误?
听起来好像您正在运行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位系统上,操作数a和b不会被提升,因此实际操作将在16位类型上执行-并且将发生无符号回绕(或在有符号变量的情况下溢出)。
困惑的程序员不了解C中隐式类型提升的工作方式,他们可能会认为执行上述操作uint32_t只是因为结果存储在这种类型中。但这是不正确的,赋值运算符的左侧与子表达式无关a + b。在子表达式中使用哪种类型完全由运算符优先级决定,并且=优先级低于+。
显然,MISRA-C认为这种误解是普遍的,这就是该规则的理由。
至于如何解决,很容易:
result = (uint32_t)1U << resolution;
Run Code Online (Sandbox Code Playgroud)