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

时间:2017-10-24 11:01:25

标签: c lint misra

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

uint32_t result;
uint8_t resolution;

result = 1U << resolution;

我尝试了以下内容:

#define SHIFT_BY_ONE (uint8_t)1
result  = SHIFT_BY_ONE << resolution;

然后会抛出此警告Shift left of signed quantity (int) 所以我想我不能正确理解这个问题。如何解决此错误?

4 个答案:

答案 0 :(得分:4)

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

为了从这个警告中了解任何内容,你必须研究基本类型(MISRA-C:2012 8.10)和复合表达(MISRA-C:2012 8.10.3)的含义。

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

  

复合表达式的值不应分配给具有更宽基本类型的对象。

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

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

    ProgrammingError: (psycopg2.ProgrammingError) must be superuser to COPY to or from a file
HINT:  Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.
 [SQL: "copy assets_temp (ticker, name) FROM 'EOD-datasets-codes.csv' DELIMITER ','  CSV;"]

在16位系统上,操作数uint16_t a = 40000; uint16_t b = 40000; uint32_t result = a + b; a不会被提升,因此实际操作将在16位类型上执行 - 并且将有一个无符号环绕(或者在签名变量的情况下溢出)。

不理解隐式类型促销在C中如何工作的迷茫程序员可能会认为上述操作只是因为结果存储在这种类型中而在b上执行。但这不正确,赋值运算符的左侧与子表达式uint32_t无关。在子表达式中使用的类型完全由运算符优先级决定,a + b的优先级低于=

显然,MISRA-C认为这种误解是常见的,这是这条规则的基本原理。

至于如何解决它,很容易:

+

答案 1 :(得分:2)

这是因为1Uuint32_t类型不匹配。使用UINT32_C(...) macro确保类型兼容性:

result = UINT32_C(1) << resolution;

答案 2 :(得分:1)

在你的系统1U上可能是16位无符号(这解释了尝试分配给32位无符号时的“更宽类型”)。

在这种情况下,我会使用long后缀作为文字:

result = 1UL << resolution;

(有些评论建议((uint32_t)1U) << resolution这将是最便携的方式)

答案 3 :(得分:0)

1U可能比uint32_t更窄(16位),因此“复合表达式分配给更广泛的基本类型”。将16位unsigned移位20不会产生0x100000,

uint32_t result;
uint8_t resolution;
result = 1U << resolution; // Potential 16-bit assignment to a 32-bit type.

resolution的狭隘性不是问题。

  

如何解决此错误?

我更愿意在有能力时避免施法并提供2种替代方案。两者都有效地首先制作目标类型的1而不进行强制转换。编译器肯定会发出优化代码。

result = 1u;
result <<= resolution;
// or 
result = (result*0u + 1u) << resolution;