是否可以在 C++ 的联合中声明匿名实例?

Is it possible to declare an anonymous instance in an union in C++?

在为裸机嵌入式系统 (STM32) 使用 low-level C++ 时,我遇到了一个 "anonymous union member" 声明的用例,其中包含非平凡的 (一个结构)类型。这种事情可能吗?

我试过下面这种代码:

struct Specialization_CR1_t
{
        uint32_t a :1 ;
        uint32_t   :31;
};

struct CR1_t
{
    union
    {
        struct
        {
            uint32_t  : 1;
            uint32_t b: 1;
            uint32_t  :30;
        } ;
        // Few tries...
        // Specialization_CR1_t {};
        // Specialization_CR1_t;
        Specialization_CR1_t () ; 
        // Fails with "expected unqualified-id before ')'"
    };
};

int main()
{
    //The goal :
    struct CR1_t CR1;
    CR1.a = 1;
    CR1.b = 0;
}

目标是避免 CR1.<thing>.a。显然,在union中直接匿名声明Specialization_CR1_t是有可能的,但是最终目标是能够使用模板和tmpl_CR1_t而不是"just"Specialization_CR1_t.

我知道此处显示的内容可能存在内存问题。然而,由于这是在裸机嵌入式环境中,内存结构是完全已知的,位被打包得很好且紧密并且工具链是固定的(位域没有问题)。

而且,由于这个结构体会直接映射到内存中,我无法承担另一个变量的开销。我的结构的总大小必须是 32 位并且写入 ab 必须只更改正确的位。

此致!

ISO C11 允许在其他 struct/unions 内部使用匿名结构。某些 C++ 编译器(包括 GNU-compatible(g++、clang++)和 MSVC++ 支持将其作为扩展。 The GCC manual has some examples.

这是 AFAIK 在 ISO C++ 中不允许的。如果您使用的编译器未实现此扩展,请参阅此答案的中间部分。


我很确定匿名联合在这里是一个转移注意力的问题,并且您尝试将 b 声明为具有 31 位的 32 位 object 时会遇到完全相同的问题填充和 1 value-bit 在任何其他上下文中使用 anonymous-struct。

如果在匿名工会内部是合法的,那么在任何地方都是合法的。 (但它不是,并且在 ISO C 中无处合法。正如@Peter 在评论中指出的那样,struct {<members>} Instance 中的名称 Instance 不能省略。如果你做到 struct foo {<members>}; 你只是在声明一个类型,而不是一个实例。)

您可能只需编写一个带有 operator=operator bool 重载的 class,您可以这样做,因为这是 C++。

(考虑用您实际尝试做的事情重新命名问题:编写一个带有位域成员的匿名结构。)

或者,如果您需要有关包装器 class 的帮助,请从 X-Y 问题退后一步,其中 anonymous-struct 方法显然已经走到了死胡同(除非有一些compiler-specific 支持它)并提出一个关于编写一个方便的包装器的新问题,该包装器将单词中的单个位公开为整数类型。使用供应商 headers、编译器扩展或普通或 C++ 运算符重载。

虽然考虑到您使用联合的方式,但您可以这样做以获得您想要的东西,至少没有模板,对吗?

struct CR1bits
{
    uint32_t a: 1;
    uint32_t b: 1;
    uint32_t  :30;
};

所以也许你应该问一些关于如何将其模板化为什么的问题,具有不同的类型名称,这些名称具有命名位的某些子集?也许 C 预处理器可以帮助解决这个问题,以一种更笨拙的方式仍然让使用这些类型的代码看起来像你想要的那样。


匿名结构是 C11 标准,或 C++ 扩展:

GNU C++ 和 MSVC 都支持匿名结构。这编译并工作:

union Obj {
   struct {       // extension: anonymous struct
      int x;
      int y;
      int z;
   };
   int elems[3];
};

a->xa->elems[0] 都访问相同的 object(假设没有填充的标准结构布局)。

显然这是标准的 ISO C11。