灵活数组变为指针

Change of flexible array into pointer

我正在努力消除我的 C 代码中出现的 MISRA 违规行为。它违反了 规则 18.7.

struct abc {
  struct header;
  uint8_t data[]; /* Line 1 */
};

此处,第 1 行导致 MISRA 违规。

我试着把它转换成:

struct abc {
  struct header;
  uint8_t *data;
};

我们可以像上面那样做还是违反了什么?

是的,你可以,因为它使结构大小具有确定性和静态性,但它也迫使你分配然后释放所需的 space for data with malloc() and free(),或者在每次实例化结构时明确地指向某个地方已经可用的 space。

您可能想在这里做的是为您的数组指定一个确定的长度。但是,如果此结构旨在实际描述数据块的 header,您可以使用 data[1] 然后让您的索引超过此值以访问其余部分(尽管 ISO C 禁止 0 长度数组) .

您的解决方案在语义上有所不同,即使它清除了违规也不会起作用。

此处的目的是创建一个结构,该结构可以作为 header 用于其后的连续数据。例如,如果您有:

struct Message
{
    struct abc info ;
    char data[128] ;
}  message ;

这样 message.info.datamessage.data 指的是同一事物,并且将 struct abc 转换为 struct Message 允许定义函数以传递任何 object 与 struct abc header。有效支持 C 中的多态性。

替换为:

struct abc 
{
  struct header;
  uint8_t* data;
};

在语义上有所不同,因为 data 成员不引用与 header 相邻的数据。复制语义也不同,并且在使用原始结构的代码上下文中它不太可能按预期工作。

GCC 支持以下语法:

struct abc 
{
  struct header;
  uint8_t data[0] ;
} ;

但它也可能不符合 MISRA 标准。一个合规的解决方案是:

struct abc 
{
  struct header;
  uint8_t data[1] ;
} ;

但这会插入一个额外的字符,任何使用此字符作为 header 的代码在通过 data 成员访问数据时可能需要适应该字符。

所有 safety-related 系统都禁止动态内存分配,因此 MISRA-C:2012 也是如此。这是规则 18.7 的基本原理:灵活的数组成员与动态分配密切相关,因此不允许。

动态分配被禁止的原因是在这类系统中不能有 non-deterministic 行为。此外,它 doesn't make any sense 在 microcontroller/RTOS 应用程序中使用动态分配。

如果对您的应用程序有意义,您可以将灵活数组成员换成指针。但是,如果它是某种协议或数据结构方式 header,您可能需要一个 fixed-size 数组。 (请注意结构填充:由于对齐和字节顺序,在结构中存储数据通信协议可能会出现问题。)