我面临违反规则1.2的MISRA C 2004“可能使用空指针。我使用的代码如下:
tm_uint8* diagBuf = 0u;
diagBuf[0] = diagBuf[0] + 0x40u;
diagBuf[2] = 0x01u;
diagBuf[0] = diagBuf[0] + 0x40u;
diagBuf[2] = 0x01u;
这只是上面指出的代码的一部分。一些陈述有“IF”条件。
有人可以指出我为什么会受到MISRA违规行为。?
答案 0 :(得分:1)
根据1999 C标准,第6.3.2节"指针",第3段
值为0的整型常量表达式,或者类型为
void *
的表达式,称为空指针常量。如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较。
(注意我已将上面第一句末尾的交叉引用删除为脚注,该脚注解释NULL
在<stddef.h>
中定义,其他标题为空指针常量)。
这意味着
tm_uint8* diagBuf = 0u;
使用空指针常量初始化diagBuf
,因为0u
是一个值为零的整数常量表达式。因此,diagBuf
被初始化为空指针。
此外还有以下陈述
diagBuf[0] = diagBuf[0] + 0x40u;
diagBuf[2] = 0x01u;
取消引用空指针。根据C标准,这是不确定的行为。
因此报告的Misra违规是完全正确的。
这种代码可以接受的情况(例如,可以为Misra规则提供豁免的理由,并在系统开发的背景下得到批准)在实践中非常有限。
答案 1 :(得分:0)
你对diagBuf影响0u(因此,0,所以为NULL),然后将它与&#34; diagBuf [0]&#34;一起使用。
分配它(malloc),或者更正声明以满足您的需要(tm_uint8 diagBuf [3];至少)
答案 2 :(得分:0)
C11 6.3.2.3陈述:
值为0的整型常量表达式,或者类型为
void *
的表达式,称为空指针常量
这是C语言中唯一可以指定值0
的指针 - 获取空指针的情况。问题中的行永远不能用于设置指向地址零的指针,因为在所有其他情况下,将整数值赋值给指针是无效的。
如果我们通过简单赋值C11 6.5.16.1的规则,则不存在=
的左操作数是指针而右操作数是算术类型的情况。此规则在标准中非常明确,int* ptr = 1234;
等代码只是无效的C并且始终是无效的C(它是标准的约束违规&#34;)。编译器在没有警告/错误的情况下通过它是垃圾而不是标准符合。
简单赋值列出了一个有效的异常(C11 6.5.16.1):
- 左操作数是原子,限定或非限定指针,右边是空指针常量
这是问题中代码编译的唯一原因。
现在,如果你真的希望指向硬件地址0,你必须写下这样的东西:
volatile uint8_t* ptr = (volatile uint8_t*)0u;
这会强制从整数0转换为指向地址0的指针。因为右操作数既不是0
也不是零{@ 1}},它不一个空指针常量,因此void*
不是空指针。
C标准清晰,MISRA-C与标准完全兼容。
与问题无关的错误和问题:
ptr
始终是一个错误。volatile
是一种将位设置为1的错误方法。如果该位已设置,则会出现大量错误。请改用diagBuf[0] + 0x40u
。假设|
是指向字节的指针,那么diagBuf
是MISRA-C:2012违反规则10.3,因为您指定了更宽的类型(&#34;基本上未签名&#34) ;)到较窄的类型。 MISRA兼容代码是:
diagBuf[0] = diagBuf[0] + 0x40u;