按位运算符违反 Misra
Misra violation with bitwise operator
我写了以下 MISRA 不喜欢的代码:
UartPtr->C &= ((uint8_t)(~SIO_C2_SBK));
和
#define SIO_C2_SBK ((uint8_t)0x01u)
和 UartPtr
定义为
UartPtr = (UartStruct*) 0x12345678; /* I know that this is also a violation of MISRA */
底层数据结构:
typedef volatile struct UartStructTag
{
uint8_t BDH;
uint8_t BDL;
uint8_t C1;
uint8_t C2;
} UartStruct;
我的 Misra 检查器抱怨第一行并指出
An integer constant expression with negative value is being converted
to an unsigned type.
但是,以下行不会导致 MISRA 出现问题:
UartPtr->C |= ((uint8_t)(SIO_C2_SBK));
所以问题出在按位取反。但是由于所有操作都直接转换为 uint8_t,因此我没有违反 MISRA 标准。谁想在这里帮助我?
在任何算术表达式中,类型小于 int
的值在处理之前会隐式转换为 int
。 C 语言不能对小于 int
的类型进行算术运算。因此,您的代码实际上是这样的:
UartPtr->C &= ((uint8_t)(~(int)(uint8_t)0x01u));
这只是
UartPtr->C &= ((uint8_t)(~1));
其中 ~1
在二进制补码架构上的值为 -2
。
要解决此问题,请在应用按位非之前转换为 unsigned
或任何其他大于 int
的无符号类型:
UartPtr->C &= ((uint8_t)(~(unsigned)SIO_C2_SBK));
与大多数 C 运算符一样,~
运算符将在应用运算符之前对操作数进行隐式整数转换。
#define SIO_C2_SBK ((uint8_t)0x01u)
所以上面的宏是问题所在,因为您将文字从 unsigned int
类型强制转换为小整数类型,这将被隐式提升。在应用 ~
之前,您最终得到 int
而不是 uint8_t
。
这违反了 MISRA-C:2004 的规则 10.1,该规则不允许产生不同符号类型的隐式转换(这种转换很危险,所以这是一个很好的规则)。
如果您不需要此宏来提供uint8_t
,那么只需删除(uint8_t
转换即可解决问题。
如果这个宏出于某种原因必须给出 uint8_t
,则将代码更改为(符合 MISRA):
UartPtr->C &= (uint8_t) ~(uint32_t)SIO_C2_SBK;
其中 uint32_t
对应于给定平台上 int
的大小。
我写了以下 MISRA 不喜欢的代码:
UartPtr->C &= ((uint8_t)(~SIO_C2_SBK));
和
#define SIO_C2_SBK ((uint8_t)0x01u)
和 UartPtr
定义为
UartPtr = (UartStruct*) 0x12345678; /* I know that this is also a violation of MISRA */
底层数据结构:
typedef volatile struct UartStructTag
{
uint8_t BDH;
uint8_t BDL;
uint8_t C1;
uint8_t C2;
} UartStruct;
我的 Misra 检查器抱怨第一行并指出
An integer constant expression with negative value is being converted to an unsigned type.
但是,以下行不会导致 MISRA 出现问题:
UartPtr->C |= ((uint8_t)(SIO_C2_SBK));
所以问题出在按位取反。但是由于所有操作都直接转换为 uint8_t,因此我没有违反 MISRA 标准。谁想在这里帮助我?
在任何算术表达式中,类型小于 int
的值在处理之前会隐式转换为 int
。 C 语言不能对小于 int
的类型进行算术运算。因此,您的代码实际上是这样的:
UartPtr->C &= ((uint8_t)(~(int)(uint8_t)0x01u));
这只是
UartPtr->C &= ((uint8_t)(~1));
其中 ~1
在二进制补码架构上的值为 -2
。
要解决此问题,请在应用按位非之前转换为 unsigned
或任何其他大于 int
的无符号类型:
UartPtr->C &= ((uint8_t)(~(unsigned)SIO_C2_SBK));
与大多数 C 运算符一样,~
运算符将在应用运算符之前对操作数进行隐式整数转换。
#define SIO_C2_SBK ((uint8_t)0x01u)
所以上面的宏是问题所在,因为您将文字从 unsigned int
类型强制转换为小整数类型,这将被隐式提升。在应用 ~
之前,您最终得到 int
而不是 uint8_t
。
这违反了 MISRA-C:2004 的规则 10.1,该规则不允许产生不同符号类型的隐式转换(这种转换很危险,所以这是一个很好的规则)。
如果您不需要此宏来提供
uint8_t
,那么只需删除(uint8_t
转换即可解决问题。如果这个宏出于某种原因必须给出
uint8_t
,则将代码更改为(符合 MISRA):UartPtr->C &= (uint8_t) ~(uint32_t)SIO_C2_SBK;
其中
uint32_t
对应于给定平台上int
的大小。