Битовые поля "инициализация в классе" приводят к "ошибке: в качестве левого операнда присваивания требуется значение l"

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

Каков правильный синтаксис для инициализации битовых полей с помощью функции "инициализация в классе" в C++11?

5 ответов

Решение

Каков правильный синтаксис для инициализации битовых полей с помощью функции "инициализация в классе" в C++11?

Вы не можете инициализировать битовые поля в классе. Параграф 9.2 стандарта C++11 определяет грамматику для деклараторов членов класса:

[...]

член-описатель:

декларатор virt-спецификатор-seq(opt) чистый-спецификатор (opt)

объявление-скобка-или-равно-инициализатор (опция)

идентификатор (opt) атрибут-спецификатор-seq(opt): константа-выражение

Как вы можете видеть, объявления для элементов битовых полей не могут быть завершены инициализатором скобок или равно.

Эта проблема была поднята как Основная проблема 1341 в стандарт C++, но была отклонена Основной рабочей группой C++ в октябре 2015 года как NAD ("не дефект") - см. http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html

Вы можете написать конструктор со списком инициализаторов, чтобы задать значения по умолчанию для ваших битовых полей.

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, например, с помощью -std=c++20при использовании не слишком свежей версии GCC/Clang.

Вы не можете (в 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 элемент.

Другие вопросы по тегам