我正在尝试编写防御代码并确保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。
一些背景:
而且,无论如何,我仅限于 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 决策相匹配。
查看个人资料了解隶属关系