任何人都可以提供与 static_assert 一起使用的 MISRA C++ 兼容的“offsetof”宏/模板/函数吗?

Rus*_*ltz 4 c++ misra c++11

我正在尝试编写防御代码并确保static_assert<>结构的成员具有特定的偏移量以满足某些硬件要求

MISRA C++ 规则 18-2-1 规定“不得使用宏 offsetof”,因此我们“取消定义了 offsetof”。

我们提供了一些模板的东西,但是它们在使用时都会失败static_assert<>

我一直无法找到static_assert<>跨编译器与 C++11 兼容的东西。

struct Commands
{
    uint32_t command[4];
};

struct DMA_Bundle
{
    struct header_
    {
        uint32_t num_of_elems;
        uint8_t reserved[60];
    } header;
    Commands array[16];
};
Run Code Online (Sandbox Code Playgroud)

我试图确保array从一开始就是 64 字节。

static_assert(offsetof(DMA_Bundle,array)==64,"zoinks");
Run Code Online (Sandbox Code Playgroud)

确实有效,但 MISRA 说但我不能使用它。(我无法与我们的功能安全人员争论:/)

我尝试过以下方法,但通常不起作用:

static_assert(offsetofarray()==64,"bar");
static_assert(myoffsetof(DMA_Bundle::array)==64,"double_zoinks");
Run Code Online (Sandbox Code Playgroud)

显式offsetofarray()constexpr 函数在 GCC 7.5.0 下确实可以工作,但在更高版本的 GCC 和 Clang(这是我们的嵌入式处理器工具使用的)下会失败。它因“static_assert 的非恒定条件”而失败。

另一个似乎抱怨“无效使用非静态数据成员‘DMA_Bundle::array’”

而且,无论如何,我只能使用 C++11。

And*_*rew 5

一些背景:

而且,无论如何,我仅限于 C++11

这是你的第一个问题......

MISRA C++:2008 只允许使用 C++:2003 - 此后的任何内容都超出范围。

MISRA C++ 规则 18-2-1 规定“不得使用宏 offsetof”,因此我们“取消定义了 offsetof”。

使用#undef违反了规定的规则 16-0-3(并且没有必要#undef offsetof


现在来说说重点:

规则 18-2-1 是必需的规则,旨在防止操作数类型不兼容时出现未定义的行为。

确实有效,但 MISRA 说但我不能使用它。(我无法与我们的功能安全人员争论:/)

许多剪贴板监视器的问题在于,它们可以在方框中打勾,但采取“MISRA 说不”的态度,而不了解 MISRA 实际所说的内容......

我的建议,尤其是仅在与 关联时使用时,static_assert()会引发偏差(请参阅第 4.3.2 节和 MISRA 合规性中的扩展指南)。

偏差是一种完全合法的方法,其中规则可能会造成不便,但未定义的行为不适用。


ETA(注意到与 Lundin 关于 C 的讨论):在 MISRA C:2004 中,有一个等效的指南(规则 20.6),同样对offsetofMISRA C:2012 施加了全面限制,该全面限制被删除,未定义的行为由一般规则 1.3

在许多方面,这使得 MISRA C++ 偏差的合理性变得更容易 - 因为基本原理将与 MISRA C 决策相匹配。

查看个人资料了解隶属关系