正在初始化结构类型的常量数组



我无法初始化自定义类型的常量数组。以下是代码:

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_castmemcpy进行类型双关。

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

最新更新