0

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

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

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

错误[P​​m123]:头文件中不应有对象或函数的定义(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 ;
}

有什么问题?

有没有办法摆脱这个问题?

4

3 回答 3

1

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 的建议。

于 2020-05-20T09:37:55.187 回答
0

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

typedef unsigned int int16u

所以我将 unsigned int 转换为未签名 int。我的问题中有一个打字错误,也就是说,我写了

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

但我的代码中正确的行是

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

我很抱歉。

于 2020-05-20T12:11:32.090 回答
0

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

但是,有一个变通方法,如果您采用MISRA 合规性……这引入了 Deviation Permits 的概念,MISRA 团队方便地为您提供了这样的使用许可inline(Permit/MISRA/C:2004/1.1.C.1 )

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

利益声明:见简介!

于 2020-05-21T04:54:46.580 回答