位域"In-class initialization"结果为"error: lvalue required as left operand of assignment"

Bit-fields "In-class initialization" results in "error: lvalue required as left operand of assignment"

本文关键字:as required left of assignment lvalue operand initialization In-class 结果 error      更新时间:2023-10-16
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 ("not a defect") -参见http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1341

使用c++ 11"类内初始化"功能初始化位字段的正确语法是什么?

不能在类中初始化位域。c++ 11标准第9.2段规定了类成员声明符的语法:

[…]

member-declarator:

声明符virt-specifier-seq(opt) pure-specifier(opt)

说明符brace-or-equal-initializer(选择)

identifier(opt) attribute-specifier-seq(opt): constant-expression

如你所见,位域成员的声明符不能以大括号或等号初始化式结束。

你可以写一个带初始化列表的构造函数,为你的位域提供默认值。

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没有提供任何默认初始化位域的语法,但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的支持,例如在使用不太新的GCC/Clang版本时使用-std=c++20

不能(在c++ 11中)在类中初始化位域。

在MSVC和gcc(带扩展)中,匿名的unionstruct代码可以让您绕过这一点。

struct bitfield {
  int i = 0;  // ok
  union {
    uint32_t raw = 0;
    struct {
      int j : 8;
      int x : 3;
    };
  };
};

中,我们将固定大小的rawunion混合在位域中,然后在类中初始化raw元素。

相关文章: