16
struct bitfield {
  int i = 0;  // ok
  int j : 8 = 0;  // error: lvalue required as left operand of assignment
};

使用 C++11“类内初始化”功能初始化位域的正确语法是什么?

4

5 回答 5

13

这是作为 C++ 标准的核心问题 1341 提出的,但在 2015 年 10 月被 C++ 核心工作组拒绝为 NAD(“不是缺陷”) - 请参阅http://open-std.org/JTC1/SC22/WG21 /docs/cwg_closed.html#1341

于 2014-05-15T13:32:26.797 回答
10

使用 C++11“类内初始化”功能初始化位域的正确语法是什么?

您不能在课堂上初始化位域。C++11 标准的第 9.2 段指定了类成员声明符的语法:

[...]

成员声明者:

声明符 virt-specifier-seq(opt) 纯说明符(opt)

声明符大括号或相等初始化器(选择)

标识符(选择)属性说明符序列(选择):常量表达式

如您所见,位域成员的声明符不能由大括号或相等初始化器终止。

于 2013-05-13T11:33:16.863 回答
2

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 版本时。

于 2022-01-20T22:17:47.363 回答
2

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

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) {};
};
于 2017-08-26T11:28:39.313 回答
1

您不能(在 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元素。

于 2014-05-15T14:14:44.417 回答