我无法初始化自定义类型的常量数组。以下是代码:
union chk {
struct{
int a : 4;
int b : 12;
}stNative;
int nVal;
};
const chk obj[2] = {0x1234, 0x6789};
int main() {
cout << obj[0].nVal<<endl;
}
在执行上面的代码时,我得到了一些随机值。我无法理解发生这种情况的原因以及如何解决。上述代码的O/P为:30868
声明中的初始化将值分配给第一个联合成员stNative
,即具有两个值的结构。您已经为具有溢出的第一个结构成员a
提供了值。此小更新将初始化两个结构成员。
#include <iostream>
using namespace std;
union chk {
struct{
int a : 4;
int b : 12;
}stNative;
int nVal;
};
const chk obj[2] = {{0x1, 0x234}, {0x6, 0x789}};
int main() {
// Undefined behaviour bellow while reading nVal
cout << std::hex << obj[0].nVal<<endl;
}
// Output: 2341
C++中不允许使用类型双关。如果初始化联合成员stNative
,则应仅读取它,不允许读取nVal
。使用std::bit_cast
或memcpy
进行类型双关。
在C++20中,您可以这样做来显式初始化特定成员:
union chk {
struct {
int a : 4;
int b : 12;
} stNative;
int nVal;
};
int main() {
const chk obj[2] = {{.nVal = 0x1234}, {.nVal = 0x6789}};
}
我想补充一点,在这种特殊情况下,嵌入聚合类型的括号省略使您成为受害者
嵌套初始值设定项列表周围的大括号可能会被省略(省略(,在这种情况下,需要尽可能多的初始值设定项子句用于初始化相应的subggregate,以及随后的初始值设定项子句用于初始化对象的以下成员。
因此,当您认为您初始化了并集的int nVal
属性时,实际上您初始化了struct stNative
。原因是(正如273Ks的答案中所指出的(,因为结构成员在并集的声明中处于第一位。
如果括号省略不是一件事,那么数组初始化必须看起来像这样(否则将被视为格式错误(:
const chk obj[2] = {{ 0x1234, 0x6789 }};