Это подходящий случай для использования union против reinterpret_cast - PullRequest
2 голосов
/ 04 апреля 2019

Я получаю четыре слова (32 бита) данных с устройства ввода-вывода.Первое слово в сообщении говорит мне, какие данные поступают. Мне было интересно, так ли это для использования union или reinterpret_cast.

Вот мой вариант использования ...

struct Plain {
  uint32_t  type;
  uint32_t data1;
  uint32_t data2;
  uint32_t data3;
}
struct Special1 {
  uint32_t  type;
  uint32_t data1;
  float    data2;
  uint32_t data3;
}

struct Special2 {
  uint32_t  type;
  uint32_t data1;
  float    data2;
  uint16_t data3;
  uint16_t data4;
}
union My_union {
  Plain    p1;
  Special1 p2;
  Special2 p3;

}
void foo(const Special1& x);
void foo(const Special2& x);
int main() {
  My_union x;
  read(&x.p1, sizeof(Plain)); // read from an IO device
  if(x.p1.type == 1)
  {
    foo(x.p2);
  }
  else
  {
    foo(x.p3);
  }
  return 0;
}

Я пытаюсь выяснить, является ли это подходящим случаем для использования союза, или же бросок все еще является способом иесли да, то почему?

1 Ответ

0 голосов
/ 05 апреля 2019

Если объект x будет правильно инициализирован, операторы if в main() будут допустимыми, поскольку, несмотря на следующее ограничение в пункте [class.union]/1 стандарта C ++:

1) В объединении нестатический элемент данных активен, если его имя относится к объекту, время жизни которого началось и не закончилось. Не более одного члена нестатических данных объекта объединенного типа может быть активным в любое время , то есть значение не более одного из нестатических данныхчлены могут быть сохранены в объединении в любое время.

следующее исключение позволяет получить доступ к общему члену type:

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

Но проблема в вашем фрагменте состоит в том, что вы создаете объект объединения x без активации какого-либо из его членов ([basic.life] / 1.2):

(...) если объект является членом объединения или его подобъектом, время его жизни начинается только в том случае, если этот член объединения является инициализированным членом объединения

Это означает, что некоторые данные считываются непосредственно в объединениеобъект, когда ни один член не активен, так что все еще ни один член не активен.Строго следуя стандарту, я бы понял, что это совсем не гарантировано.

Правильный способ сделать это - прочитать type, затем инициализировать соответствующий член и прочитать в нем остальную часть структуры (или прочитать все в буфер и скопировать, следуя аналогичной стратегии),Однако на практике ваш код будет работать на большинстве компиляторов.

...