struct bitfield {
int i = 0; // ok
int j : 8 = 0; // error: lvalue required as left operand of assignment
};
使用 C++11“类内初始化”功能初始化位域的正确语法是什么?
struct bitfield {
int i = 0; // ok
int j : 8 = 0; // error: lvalue required as left operand of assignment
};
使用 C++11“类内初始化”功能初始化位域的正确语法是什么?
这是作为 C++ 标准的核心问题 1341 提出的,但在 2015 年 10 月被 C++ 核心工作组拒绝为 NAD(“不是缺陷”) - 请参阅http://open-std.org/JTC1/SC22/WG21 /docs/cwg_closed.html#1341
使用 C++11“类内初始化”功能初始化位域的正确语法是什么?
您不能在课堂上初始化位域。C++11 标准的第 9.2 段指定了类成员声明符的语法:
[...]
成员声明者:
声明符 virt-specifier-seq(opt) 纯说明符(opt)
声明符大括号或相等初始化器(选择)
标识符(选择)属性说明符序列(选择):常量表达式
如您所见,位域成员的声明符不能由大括号或相等初始化器终止。
C++11 没有为默认初始化位域提供任何语法,但C++20 提供了.
这意味着当您的 C++ 编译器支持 C++20 时,您的示例可以正常编译:
struct bitfield {
int i = 0; // ok
int j : 8 = 0; // ok since C++20
int k : 8 {0}; // ditto
};
请注意,您可能需要显式启用 C++20 支持,例如-std=c++20
在使用不太新的 GCC/Clang 版本时。
您可以编写一个带有初始化列表的构造函数,为您的位域提供默认值。
struct bitfield {
int i;
int j : 8;
bitfield() : i(0), j(0) {};
};
您还可以使用默认值创建只读字段。
struct _UserRegister1
{
uint8_t _RES0 : 1;
const uint8_t reserved1 : 1;
uint8_t _HTRE : 1;
const uint8_t reserved2 : 3;
uint8_t _VDDS : 1;
uint8_t _RES1 : 1;
_UserRegister1() : reserved1(1), reserved2(7) {};
};
您不能(在 C++11 中)类内初始化位域。
在 MSVC 和 gcc(带有扩展名)中,匿名union
和struct
代码可以让您稍微绕过这个问题。
struct bitfield {
int i = 0; // ok
union {
uint32_t raw = 0;
struct {
int j : 8;
int x : 3;
};
};
};
我们将固定大小raw
与union
过度位域混合,然后在类中初始化raw
元素。