如何正确初始化包含联合体的C++结构体?

3

MISRA-C++规则8-5-2要求使用正确的大括号初始化C ++结构。我有一个带有联合体的结构,我无法找到正确的大括号组合来满足此规则。我不确定我的代码是否不正确,或者是静态代码分析工具发出了错误的警告。

这是该结构:

typedef struct XMC_VADC_RESULT_CONFIG
{
    union
    {
       struct
       {
          uint32_t                         : 16;
          uint32_t data_reduction_control  : 4;  /**< Configures the data reduction stages */
          uint32_t post_processing_mode    : 2;  /**< Result data processing mode. Uses @ref  XMC_VADC_DMM_t
                                                      For normal operation select
                                                      XMC_VADC_DMM_t::XMC_VADC_DMM_REDUCTION_MODE
                                                      and data_reduction_control as 0*/
          uint32_t                         : 2;
          uint32_t wait_for_read_mode      : 1;  /**< Allow the conversion only after previous results are read*/
          uint32_t part_of_fifo            : 2;  /**< Make the result register a part of Result FIFO? */
          uint32_t                         : 4;
          uint32_t event_gen_enable        : 1;  /**< Generates an event on availability of new result. */
       };
       uint32_t g_rcr;
    };
} XMC_VADC_RESULT_CONFIG_t;

这是我的初始化代码:

    const XMC_VADC_RESULT_CONFIG_t resultConfig = 
{
  {
    {
    .data_reduction_control     = 0U,                                                   // No Accumulation
    .post_processing_mode       = static_cast<uint32_t>(XMC_VADC_DMM_REDUCTION_MODE),
    .wait_for_read_mode         = 0U,                                                   // Disabled
    .part_of_fifo               = 0U,                                                   // No FIFO
    .event_gen_enable           = 0U                                                    // Disable Result event
    }
  }
};

我也试过去掉一对大括号,但没有帮助。 正确的大括号数量是多少?


请注意,MISRA C++:2008的规则9-5-1指出,根本不应使用联合体(_“(必需)不得使用联合体”_); 因此,请注意,如果您想继续使用联合体,则需要正式偏离此规则。 - dfrib
是的,我看到了这个。我的问题是结构定义在微控制器制造商提供的库中。我必须使用这个库。在这种情况下,使用联合体访问整个寄存器或单个位也是有意义的。 - amanning
我认为MISRA禁止使用联合体,因为在C++中通过联合体进行类型转换通常是未定义的行为。 - Caleth
@amanning 很可能该库假定使用的是非 MISRA C 标准,而不是 MISRA-C++。为什么您一定要使用 C++ 呢?它并不适合用于声明寄存器映射。 - Lundin
这个库是用C语言编写的,但我们的应用程序是用C++编写的,因此初始化在C++中进行。 - amanning
2个回答

2
  • 正确且符合规范的支架放置应该是 const XMC_VADC_RESULT_CONFIG_t resultConfig = { 0u };
  • MISRA-C++ 要求使用 C++03,因此不能使用其他版本。
  • 指定初始化程序(.name 语法)是 C 的东西,只存在于 C99 及以上版本。它们不允许在 MISRA-C:2004 中使用,但在 MISRA-C:2012 中可以使用一些特殊规则。在 C++ 中,它们最近才被引入,但不能在 MISRA 兼容的应用程序中使用。
  • union 类型双关语通常在任何 MISRA 中都不被允许,特别是在 C++ 中,它是未定义行为。在 C 中有一些例外情况,但在 C++ 中没有。
  • 位字段在任何关键应用程序中的存在,无论是否为 MISRA,都是高度可疑的做法,因为它们标准化的程度非常低。

总结:您无法在任何形式的 MISRA 应用程序中使用此代码。删除 union 和位字段并将其替换为按位运算符和位掩码。


是的,当你从那些生活在石头下(或QFP下)自1998年以来从未编写过一行专业代码的不靠谱MCU硅供应商手中接收到一个松散的寄存器映射表时,这是一个巨大的问题。因此,在大多数情况下,为了严格遵守MISRA标准,您必须推出自己的寄存器映射表。我在这里写了一些建议:如何从固件访问硬件寄存器? - Lundin
如果你很幸运的话,一些商业工具链可能会有真正符合MISRA标准的库,但我个人还没有遇到过这样的情况。 - Lundin
我们的代码不必符合MISRA标准,我们只需在静态代码分析器中使用MISRA设置来尽可能地捕获许多漏洞。 - amanning
@amanning 好的,恭喜你找到了一个。C++ 不允许联合类型转换(不像 C),所以你不能在 C++ 中使用这个寄存器映射。 - Lundin

0

C++在C++20之前没有指定初始化器,所以你必须放弃它们。

const XMC_VADC_RESULT_CONFIG_t resultConfig = 
{
  {
    {
      0U,                                                   // No Accumulation
      static_cast<uint32_t>(XMC_VADC_DMM_REDUCTION_MODE),
      0U,                                                   // Disabled
      0U,                                                   // No FIFO
      0U                                                    // Disable Result event
    }
  }
};

我们的Clang编译器设置为C++14,但它接受指定初始化器,我认为这非常好,因为它使得阅读代码更加容易,你可以看到正在初始化的内容,而不必添加任何注释。 - amanning

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接