我写了以下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检查员抱怨第一行并说明,
正在转换具有负值的整数常量表达式 到无符号类型。
但是,以下行不会导致MISRA出现问题:
UartPtr->C |= ((uint8_t)(SIO_C2_SBK));
所以问题来自于按位否定。但由于所有操作都直接转换为uint8_t,因此我不会违反MISRA标准。谁想帮助我?
答案 0 :(得分:6)
在任何算术表达式中,小于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));
答案 1 :(得分:4)
与大多数C运算符一样,~
运算符将在应用运算符之前对操作数进行隐式整数转换。
#define SIO_C2_SBK ((uint8_t)0x01u)
所以上面的宏是个问题,因为你强迫文字从unsigned int
类型下降到一个小的整数类型,这将被隐式提升。在应用uint8_t
之前,而不是int
,而不是~
。
这违反了MISRA-C:2004的规则10.1,它不允许隐式转换产生一种不同的签名(这种转换是危险的,因此这是一个非常好的规则)。
如果您不需要此宏来提供uint8_t
,那么只需删除(uint8_t
广告,即可解决问题。
如果由于某种原因此宏必须提供uint8_t
,请将代码更改为此(符合MISRA):
UartPtr->C &= (uint8_t) ~(uint32_t)SIO_C2_SBK;
其中uint32_t
对应于给定平台上int
的大小。