【发布时间】:2018-11-17 02:03:31
【问题描述】:
我正面临着我无法理解的 MISRA C 2012 违规行为。以下是代码:
#define I2C_CCRH_FS ((uint8_t)0x80)
#define I2C_CCRH_DUTY ((uint8_t)0x40)
#define I2C_CCRH_CCR ((uint8_t)0x0F)
typedef struct I2C_struct
{
volatile uint8_t CR1;
volatile uint8_t CR2;
volatile uint8_t CCRL;
volatile uint8_t CCRH;
} I2C_TypeDef;
#define I2C_BaseAddress 0x5210
#define I2C ((I2C_TypeDef *) I2C_BaseAddress)
I2C->CCRH &= ~(uint8_t)((I2C_CCRH_FS | I2C_CCRH_DUTY) | I2C_CCRH_CCR);
在前面的代码中,PC-Lint 抱怨:
Unpermitted operand to operator '|' [MISRA 2012 Rule 10.1, required]
Mismatched essential type categories for binary operand [MISRA 2012 Rule 10.4, required]
规则 10.1 规定 ORing unsigned ints 应该没有问题。 (PC-Lint 通过了第一个 OR 操作并抱怨第二个!)
规则 10.4 规定操作的操作数应具有相同的基本类型。
尽管所有操作数都声明为uint8_t,但我不明白为什么存在这些违规行为?
我尝试在每两个 ORed 常量周围加上括号。我还尝试将它们全部转换为uint8_t 和volatile uint8_t。未解决违规问题。
【问题讨论】:
-
不是你的问题,而是:你为什么写
(I2C_CCRH_FS | I2C_CCRH_DUTY) | I2C_CCRH_CCR?没有括号的I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR会不会有什么问题? -
如果解决方案是添加额外的演员,就像在接受的答案中一样(这让我觉得这是一个经典的例子,为了安抚风格指南而制作代码 worse,但是那是另一个问题),在我看来,最好消除原始位掩码定义中的强制转换。为什么不直接说
#define I2C_CCRH_FS 0x80之类的? (或者#define I2C_CCRH_FS 0x80u,如果强调它们是未签名的很重要?)这样你也不需要在表达式中进行任何强制转换。 MISRA 会很高兴,那些(正确地)不赞成明确演员表的人也会很高兴。 -
这段代码是我在项目中使用的一个大库(stm库)的sn-p,因此很难更改变量的定义。当我在做一个与安全相关的项目时,我必须对照 MISRA 检查这个库。我接受的答案刚刚解决了这个问题。我认为没有更好的解决方案。是的,我有一行代码,其中 10 个操作数之间存在 ORing。因此,将每个结果转换为
uint8_t会使代码更难阅读并且更容易出错。所以我决定只禁用此特定行的错误消息。你有更好的解决方案吗? -
这最终成为一个难以思考的问题,恐怕我无法为您提供建议。您的首要目标是 (a) 使代码安全,(b) 使代码可读,(c) 满足 MISRA,还是 (d) 避免需要大量审查和批准以致成本过高的大规模更改? (不幸的是,目标(a)、(b)和(c)并不总是一致的。)如果是我,我会毫不犹豫地删除定义中的演员表——但这只是我,我不能充分权衡我的选择与目标 (c) 和 (d),因为这些目标从未应用于我的工作。
-
@SteveSummit 我会做所有的 a、b、c 和 d,看看我的答案 :) 删除演员表并使用
u后缀让 MISRA 很开心,代码也很安全。
标签: c implicit-conversion lint type-mismatch misra