违反MISRA 2012-类型不匹配(规则10.1、10.4) [英] MISRA 2012 violation - Type mismatch (Rules 10.1, 10.4)

查看:696
本文介绍了违反MISRA 2012-类型不匹配(规则10.1、10.4)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正面临无法理解的MISRA C 2012违规行为.以下是代码:

I'm facing MISRA C 2012 violation that I can't understand. Following is the code:

#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抱怨:

In the previous code, PC-Lint complains that:

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指出对unsigned int进行OR运算应该没有问题. ( PC-Lint通过第一个或"运算,并抱怨第二个!! )

Rule 10.1 states that there should be no problem ORing unsigned ints. (PC-Lint passes the first OR operation and complains about the second one!!)

第10.4条规定,该操作的操作数应具有相同的基本类型.

Rule 10.4 states that the operands of the operation shall have the same essential type.

尽管所有操作数都声明为uint8_t,我不明白为什么存在这些冲突?

I can't understand why these violations exist although all of the operands are declared as uint8_t?

我尝试在每两个ORed常数之间加上括号.我也尝试过将它们全部转换为uint8_tvolatile uint8_t.未解决违规问题.

I've tried puting parentheses around each two of the ORed constants. I've also tried casting all of them to uint8_t and to volatile uint8_t. Non solved the violation.

我检查了这两篇文章( 1 2 ),但他们没有回答我的问题.

I checked these two posts (1, 2) but they don't answer my question.

推荐答案

I2C_CCRH_FS | I2C_CCRH_DUTY本身就是MISRA兼容的.两个操作数本质上都是无符号的,因此子表达式很好.但是,仍然存在每个操作数到int的隐式转换.实际上,结果是int类型.

I2C_CCRH_FS | I2C_CCRH_DUTY is MISRA-compliant by itself. Both operands are essentially unsigned so that sub-expression is fine. However, there is still an implicit conversion of each operand to int. The result in practice is of type int.

在伪代码中:执行(result as int) | I2C_CCRH_CCR时,隐式提升之前的操作数的类型为int | uint8_t. uint8_t也会在这里提升为int的整数.您具有不同符号的操作数.

In pseudo code: when you do (result as int) | I2C_CCRH_CCR, the operands before implicit promotion have the types int | uint8_t. The uint8_t will get integer promoted to int here too. You have operands of different signedness.

(我想这个工具抱怨10.4,因为整数提升是通常的算术会话的一部分,这就是10.4的含义.)

(I guess that the tool complains about 10.4 since the integer promotions are part of the usual arithmetic conversiosn, which is what 10.4 is about.)

在实践中,整个表达式不会引起任何问题,因此该警告大部分是ped脚的.但是想像一下,如果您不使用强制转换而执行~(I2C_CCRH_FS | I2C_CCRH_DUTY) | I2C_CCRH_CCR) -您最终将得到一个负数,该数字沿0xFFFFFFxx的行以2的补码表示.那可能很危险.

This whole expression doesn't cause any problems in practice so the warning is mostly pedantic. But imagine if you had done ~(I2C_CCRH_FS | I2C_CCRH_DUTY) | I2C_CCRH_CCR) with no casts - you'd end up with a negative number, something along the lines of 0xFFFFFFxx expressed in 2's complement. That would potentially be dangerous.

要解决此问题,您有两种选择:

To fix this, you have two options:

  • 对于每个操作,都将结果强制转换回预期的类型.这通常是MISRA-C的精神.
  • 在操作前将操作数转换为大的无符号类型.通常更具可读性的IMO.

还请注意,~运算符不应与带符号的操作数一起使用!这违反了规则10.1.最后转换回uint8_t的操作.

Note also that the ~ operator should not be used with a signed operand! This is a violation of rule 10.1. The cast back to uint8_t should be done last.

TL; DR.如何使代码符合MISRA:

您要么要做这样的半可怕的事情:

You'd either have to do something semi-awful like this:

I2C->CCRH &= (uint8_t) ~ (uint8_t) ((uint8_t)(I2C_CCRH_FS | I2C_CCRH_DUTY) | I2C_CCRH_CCR)

有点混乱.我宁愿提前投.假设32位CPU:

That's a bit of a mess. I would instead cast in advance. Assuming 32 bit CPU:

I2C->CCRH &= (uint8_t) ~( (uint32_t)I2C_CCRH_FS    |  // comment explaining FS
                          (uint32_t)I2C_CCRH_DUTY) |  // comment explaining DUTY
                          (uint32_t)I2C_CCRH_CCR   ); // comment explaining CCR

上面的样式在处理MCU寄存器和类似寄存器时很有用.该代码是可以接受的,但可以进一步简化.

The above style is useful when dealing with MCU registers and similar. This code is acceptable, but could be simplified further.

如果可以将定义更改为#define I2C_CCRH_FS 0x80u,那么您将得到:

If it is possible to change the defines to #define I2C_CCRH_FS 0x80u, then you get:

I2C->CCRH &= (uint8_t) ~(I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR);

,由于MISRA喜欢的方便的u后缀,它仍然符合MISRA.

and it would still be MISRA compliant, because of the handy little u suffix that MISRA likes.

这篇关于违反MISRA 2012-类型不匹配(规则10.1、10.4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆