2012-07-19 93 views
26

我建立了一个工作的C库,使用常量,在头文件中定义为联盟初始化++和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++中使用它们。

+0

你确定混合模式标签? – 2012-07-19 07:17:46

+2

是不是C++初始化第一个元素的'union's?即'static const Y_CONSTANT = {{0,0,0,0}};' – YePhIcK 2012-07-19 07:19:48

+0

@YePhIcK然后它给出了关于丢失大括号的其他警告。 – Alex 2012-07-19 07:22:06

回答

15

我有同样的问题。对于C89以下为真:

随着C89风格的初始化,结构成员必须在 初始化命令宣布,只有联合的第一个成员可以是 初始化

我发现这个解释在: Initialization of structures and unions

3

我相信C++ 11允许你写你自己的构造函数,像这样:

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

    Foo() : raw{} { } 
}; 

此默认初始化Foo型与积极成员raw,它具有所有元素初始化为零的工会。 (在C++ 11之前,没有办法初始化那些不是完整对象的数组)。

+0

我怀疑,一个构造函数可以被C编译器解析.. – Alex 2012-07-19 07:33:54

+1

@Alex:不,当然不是。但是运气好的话,这个结构将会和布局兼容,并且具有类似声明的C结构。 – 2012-07-19 07:35:58

+0

啊我看到了,所以你想建议在正确的位置使用'#ifdef __cplusplus'来使这个头文件可以被包含。啊,这可能会变得更加模糊。 – Alex 2012-07-19 07:39:07

1

C89允许通过直接列出你想要初始化的元素(就像你在代码中所拥有的)来初始化联合。 C99已经改变了这一点,以便你可以通过它的第一个元素来创建一个工会。

C++只允许这种形式的初始化 - 通过第一个元素。所以这是代码应该工作正常的任一情况:

static const CardInfo Y_CONSTANT = {{0, 0, 0, 0 } }; 
+6

你有这个倒退。 C89/C90只允许初始化第一个成员。 C99保持相同的功能(以避免破坏现有代码),但添加了指定的初始化程序。您的声明不是有效的C++,除非{0,0,0,0}是类型为struct struct_field_的有效初始值设定项。 – 2012-07-19 08:32:36

2

我决定选择以下路径。

  • 不要使用.member初始化。
  • 做NOST使用static const struct Foobar初始化成员

相反声明全局变量:

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

并初始化它在全球部分:

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

和替代窃听的C++具有现代ANSI C99语法的编译器我让链接器完成这项工作,将C符号解映射。

+0

“* ANSI C99 *”... – Spookbuster 2017-11-01 21:08:59

+0

@Spookbuster https://en.wikipedia.org/wiki/ANSI_C#C99是的? – Alex 2017-11-01 21:23:46