What is the correct way to initialize C++ structures with unions?

782 views Asked by At

The MISRA-C++ rule 8-5-2 requires that C++ structures are initialized with the correct braces. I have a structure with unions and I connot find the correct combination of braces to satisfy this rule. I am not sure if my code is incorrect or false positive warning from the static code analyser tool.

This is the structure:

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;

This is my initialization code:

    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
    }
  }
};

I have also tried removing one set of braces, but that didn't help. What is the correct number of braces?

2

There are 2 answers

1
Caleth On

C++ doesn't have designated initializers until C++20, so you will have drop those.

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
    }
  }
};
4
Lundin On
  • Correct, compliant brace placement would be const XMC_VADC_RESULT_CONFIG_t resultConfig = { 0u };
  • MISRA-C++ requires C++03 so you can't use anything else.
  • Designated initializers (the .name syntax) is a C thing that only existed from C99 and beyond. They aren't allowed in MISRA-C:2004, but in MISRA-C:2012 (with some special rules). In C++ they have only been introduced recently, in a version of C++ that you are not allowed to use in MISRA compliant applications.
  • union type punning is in general not allowed in any MISRA, particularly not in C++ where it is undefined behavior. A few exceptions to the rule exist in C, but not in C++.
  • The presence of bit-fields in any critical application, MISRA or not, is highly questionable practice since they are so poorly standardized.

Summary: you can't use this code in any form of MISRA application. Drop the union and bit-field both and replace them with bitwise operators and bit masking.