头文件中的静态内联函数和 MISRA C 规则 8.5 问题



我正在使用"IAR RL78"和"RL78-R5F10BGG"微控制器。我还在IAR中启用了MISRA C 2004。

我想将我的一个函数定义为"内联"。这个内联函数应该在各种c文件中使用。所以我在我的一个函数中定义了这个函数

头文件,并将该头文件包含在需要该功能的所有 C 文件中。但我的问题是因为编译后的 MISRA C 8.5 规则。它说:

错误[Pm123]:头文件中不应定义对象或函数(MISRA C 2004 规则 8.5(

以下是 common.h 标头中内联函数的定义:

static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex);
#pragma inline=forced
static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex)
{
int16uVar |= ( (int16u)1u << (int16uBitIndex) );
return int16uVar ;
}

怎么了?

有什么办法可以解决这个问题吗?

MISRA-C:2004 不包括 C99,因此您根本无法使用inline

正因为如此,即使在内联函数中,关于头文件中函数定义的规则也会直截了当地打击。您无法通过发布的代码符合 MISRA-C:2004 - 您将不得不创建与几个必需规则的偏差。


我的建议是升级到MISRA-C:2012,这种情况有一个明确的例外(规则5.9(:

例外
可以在多个翻译单元中定义具有内部链接的内联函数,前提是所有此类定义都在每个翻译单元中包含的同一头文件中进行。

MISRA-C:2012还要求所有内联函数必须声明为static(规则8.10(。

MISRA-C:2012几乎在各个方面都是一份更好的文件。IAR也支持2012版本,他们的MISRA检查器应该是一个单独的插件,与特定的MCU无关。


与您的实际问题无关(int16u)1u <<是完全错误和危险的。

如果您实际上必须具有有符号类型(通常您没有(,那么您必须首先对无符号类型执行移位,然后转换为有符号类型。

这不仅需要符合 MISRA-C 标准,而且需要修复一个明显的 C 错误,当您将数据左移到符号位时,该错误会在 8 位和 16 位 MCU 上调用未定义的行为。

应该int16uVar |= (int16u)(1u << int16uBitIndex);正确的代码,我相信这也满足了 MISRA-C:2004 关于在操作后转换为底层类型的要求。


另请注意,创建自己的"车库标准"整数类型通常不受欢迎 - 因为您使用的是 C99,您应该使用stdint.h而不是其他任何东西。这也是MISRA-C:2012的建议。

谢谢伦丁的有用回复。 关于您回复的第二部分,我应该说在我们的编码风格中,我们将 int16u 用于无符号的 int 类型。那是

typedef unsigned int int16u

所以我正在移动无符号的 int 未签名的 int。 我的问题中有一个打字错误,那就是,我已经写了

int16uVar |= ( (int16u)1u << (int16uBitIndex) );

但是我的代码中的正确行是

int16uVar |= ( (int16u)1 << (int16uBitIndex) );

我很抱歉。

简单来说,inline不是C90的一部分(如MISRA C:2004所涵盖的(

但是,如果您采用 MISRA 合规性,则有一种解决方法...这引入了偏差许可证的概念,MISRA团队方便地为您提供了使用inline的许可证(许可证/MISRA/C:2004/1.1.C.1(

当然,大多数编译器无论如何都会忽略内联限定符......

利益声明:请参阅个人资料!

最新更新