如何(1<< 9)通过MISRA?

时间:2014-02-03 20:26:48

标签: c bit-shift c-preprocessor misra

我们正在使用Parasoft Static Analysis并启用了MISRA C 2004检查程序。

该软件是一个嵌入式系统。我们喜欢按如下方式描述常量:

[1]    #define MOTOR_ON (1 << 9)  

这表明寄存器中的第9位应为1以打开电机。

表达式是MISRA失败,所以我们改变了它:

[2]    #define MOTOR_ON (1U << 9U)

更改转换为无符号整数常量,因为最好使用无符号整数进行移位。

语句2中的表达式仍然失败,因为右手操作符(9U)需要检查。根据MISRA,如果右手操作符大于左手操作符的底层类型的位宽,则存在问题。

问题的根源是1U的基础类型为unsigned char或8位 我们写的寄存器是16位,所以理论上没有问题。

如何更改[2]中的表达式,使其通过MISRA C 2004,更喜欢不使用强制转换?

我正在使用IAR Embedded Workbench和8/32位模式的ARM7TDMI处理器。

编辑1:示例代码。

void turn_on_motor(void);
#define MOTOR_ON (1U << 9U)
void turn_on_motor(void)
{
    uint16_t * const p_motor_control = (uint16_t *)(0x01234567U);
    *p_motor_control = MOTOR_ON;
}

错误文本:用作移位运算符右侧操作数的常量应受限制。

来自Parasoft提供的MISRA规则文档:

Rule reports a violation if:

- the right-hand operand is a constant with negative value or with value that
  exceeds the length (in bits) of the left-hand operand

- the right-hand operand is not a constant and is not checked by specific
  pattern

3 个答案:

答案 0 :(得分:3)

我的建议是定义一个隐藏丑陋铸造的宏,然后继续进行丑陋的施法以使MISRA高兴。

类似的东西:

#define LSHIFT(x, n) \
    (((unsigned int)(x)) << ((unsigned int)(n)))

然后在您的实际代码中:

#define MOTOR_ON LSHIFT(1, 9)

编辑:在下面的评论中,@ Lundin说MISRA会抱怨类似函数的宏。我从未使用过MISRA所以我不知道。

快速Google搜索会发现MISRA有一些特殊注释可以添加到您的代码中以禁用警告。这表明有两种可能性:

  • 在定义LSHIFT()RSHIFT()以及任何其他位操作宏的头文件中,将宏定义包装在MISRA警告禁用注释中。

  • 在您想要进行位移的源文件中,添加MISRA警告禁用注释,然后将代码放在之前。

http://www.gimpel.com/Discussion.cfm?ThreadMode=Prev&ThreadID=2261

如果我理解正确,MISRA具有全局启用/禁用功能,但没有禁用,然后“按原样放回”。因此,禁用然后启用的注释将始终全局启用检查,因此理想情况下,这些魔术注释不应位于头文件中。

所以我想我现在的建议是将原来的位移代码放在.C源文件中,然后将魔术注释用于禁用/启用位移代码周围的MISRA警告。

答案 1 :(得分:1)

你也可以通过使用

来避免转移问题
 #define MOTOR_ON ((uint16_t)512U)   /* 1 << 9 = 2^9 */

答案 2 :(得分:0)

表达式的值被分配给具有较窄类型的对象。 “1U&lt;&lt; 9U“仅导致保留低位。

用丑陋的演员“让MISRA高兴”不会改变这个事实,虽然一个糟糕的工具可能会被游戏,但它不应该。

直截了当的解决方案是使用显式转换:

#define MOTOR_ON ((uint16_t)0x200) /* 9th bit on turns on motor */

但是如果您认为“转换更易于阅读”,那么只需关闭此案例的规则并记录推理。如果事实上完全符合性是不可能的,那么在符合MISRA的开发中,偏差过程是完全正确的(并且是鼓励的)。您必须让偏差管理流程完全符合要求。意识的证据是目标,而不是一致性的证据。

BTW,@ Thomas,你说得对,这也不是你写的MISRA C:2004, error with bit shifting的完全重复。虽然它违反了规则10.3,但所描述的“基础类型”概念对于理解此警告对此特定问题的意图几乎没有帮助。我向大家提出的建议是看看最新版本的MISRA-C:2012中的规则10.3的描述(见http://misra.org.uk),这使得工程师和工具制造商的概念和意图更加清晰。