空指针问题

时间:2018-03-14 10:40:28

标签: c pointers null-pointer misra

我面临违反规则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违规行为。?

3 个答案:

答案 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;