在符合 MISRA 的情况下在 C 中传递缓冲区

Passing buffers in C with MISRA compliance

MISRA 让我们的开发人员感到沮丧。

我们收到关于 "Do not apply pointer arithmetic to pointer" 和 "pointer does not point to array" 的 MISRA 错误。

我们使用的语法是:

uint8_t const * p_buffer

将缓冲区传递给将缓冲区写入 SPI 总线的函数。

给出示例代码片段:

static void Write_Byte_To_SPI_Bus(uint8_t byte);

void Write_Buffer_To_SPI_Bus(uint8_t const * p_buffer,
                             unsigned int quantity)
{
  for (unsigned int i = 0; i < quantity; ++i)
  {
    Write_Byte_To_SPI_Bus(*p_buffer++);
  }
}

有没有一种方法可以让指针指向数组中的单元格并递增它以满足 MISRA?

我的解释是 MISRA 想要递增数组的索引而不是指针:

void Write_Array_To_SPI_Bus(uint8_t const p_array[],
                            unsigned int quantity)
    {
      for (unsigned int i = 0; i < quantity; ++i)
      {
        Write_Byte_To_SPI_Bus(p_array[i]);
      }
    }

许多开发人员都是老派,更喜欢使用指向 uint8_t 的指针而不是传递数组。

请记住,就 C 而言,

void Write_Buffer_To_SPI_Bus(uint8_t const * p_buffer,
                             unsigned int quantity)

void Write_Array_To_SPI_Bus(uint8_t const p_array[],
                            unsigned int quantity)

意思完全一样;在函数参数声明的上下文中,uint8_t const * p_bufferuint8_t const p_array[] 都声明了 pointer 类型,而不是指针和数组类型。

您的第二个代码段应该满足 MISRA,并且实际上与第一个代码段相同。

John Bode 已经就您的第二个代码片段如何(实际上)解决了 MISRA 准则做出了答复。

我会回答你的问题"Is there a way to have a pointer to a cell in an array and increment it that will satisfy MISRA?"

简短的回答是 "no"。规则 17.4(在 MISRA 2004 中——我手边没有 2012 版本)规定 "Array indexing shall be the only allowed form of pointer arithmetic"。这基本上是您在这种情况下需要进行的更改的基础。

更长的答案是,MISRA 准则基于这样一个前提,即数组语法在某种程度上比指针取消引用更安全。我个人的看法是,这是 MISRA 的一个弱点,因为它没有解决数组索引越界的问题——这实际上与超出数组边界的指针运算具有相同的结果。

此外,隐藏变量的 "old school" 方法(使用基于索引的循环,并在循环中递增指针)也不是很好的做法。它具有 MISRA 准则试图防止的所有安全性缺乏,加上使代码更难阅读(人类必须更加努力地理解 [=10= 的值之间存在一对一的关系) ] 和 p_buffer - 更难理解的代码更容易出错)。

MISRA is frustrating our developers.

具体来说,严格遵守 MISRA 会让您的开发人员感到沮丧。

在您突出显示的情况下,偏差是一种适当的机制...