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