C++和C中的联合初始化

38

我已经构建了一个可用的C语言库,其中使用常量,在头文件中进行定义,如下所示:

typedef struct Y {
  union {
    struct bit_field bits;
    uint8_t raw[4];
  } X;
} CardInfo;

static const CardInfo Y_CONSTANT = { .raw = {0, 0, 0, 0 } };

我知道.raw初始化程序只是 C 语言的语法。

如何定义一个包含联合体的常量,以便我可以在 C 和 C++ 中使用它们。


1
你确定使用混合模式标签吗? - Sebastian Mach
2
C++ 不是通过第一个元素初始化联合体吗?比如说 static const Y_CONSTANT = {{0,0,0,0}}; - YePhIcK
@Alex - 我刚试了一下我的代码,它可以正常构建,没有任何错误/警告。你确定你在使用双括号吗?typedef struct Y { union { struct bit_field bits; uint8_t raw[4]; } X; } CardInfo;static const CardInfo Y_CONSTANT = {{0, 0, 0, 0 } }; - YePhIcK
@YePhIcK 好的,花括号似乎是个好办法,只要使用正确数量和正确顺序,但这将限制我只能初始化联合类型中的一个选择,从而无法初始化第二个。 - Alexander Oh
1
这是正确的,也是语言的规定 - 你可以初始化联合体的第一个元素,但只能是第一个。 - YePhIcK
显示剩余4条评论
3个回答

24

我遇到了同样的问题。对于C89,以下是正确的:

使用C89风格的初始化器时,结构体成员必须按照声明的顺序进行初始化,而联合体只能初始化第一个成员。

我在此网址找到了解释: Initialization of structures and unions


7

我相信C++11允许您编写自己的构造函数,如下所示:

union Foo
{
    X x;
    uint8_t raw[sizeof(X)];

    Foo() : raw{} { }
};

这将以Foo类型的联合体为默认初始值,并激活成员raw,其中所有元素均为零初始化。(在C++11之前,无法初始化不完整对象的数组。)

1
@Alex:当然不是。但是如果运气好的话,这个结构体将与类似声明的C结构体布局兼容... - Kerrek SB
啊,我明白了,你想建议在正确的位置使用 #ifdef __cplusplus 以使头文件可包含。啊,这可能会更加模糊。 - Alexander Oh
3
警告:添加构造函数将取消POD特性,而在操作联合体进行内存访问时通常希望保留该特性。 - Offirmo
3
C++11引入了一个新术语“标准布局类”,这些类允许具有构造函数;许多在C++03中需要POD的情况现在只需要标准布局。 (现在,POD被定义为标准布局加上其他一些保证)。 - M.M

2
我将选择以下路径:
  • 不使用.member初始化。
  • 不使用static const struct Foobar成员初始化。

相反,声明全局变量:

extern "C" {
  extern const struct Foobar foobar;
}

并在全局部分初始化它:

struct Foobar foobar = { 0, 0, 0, 0 };

我不使用现代 ANSI C99 语法来烦扰 C++ 编译器,而是让链接器通过去除 C 符号的装饰来完成工作。


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