Подтвердить что ты не робот

Назначение между членами профсоюза

Является ли этот код корректным?

int main()    
{    
    union     
    {    
        int i;    
        float f;    
    } u;    

    u.f = 5.0;    
    u.i = u.f;       // ?????
}    

Он обращается к двум различным членам профсоюза в одном выражении, поэтому я задаюсь вопросом, не попадает ли это в положения [class.union]/1 об активном члене профсоюза.

Стандарт С++, похоже, указывает, какие операции изменяют активный элемент для встроенных типов, и что происходит, если неактивный элемент читается или записывается.

4b9b3361

Ответ 1

Оператор присваивания (=) и составные операторы присваивания все группы справа налево. [...] Во всех случаях присваивание секвенируется после значение вычисление правого и левого операндов и перед вычислением значения выражения присваивания. [...]

[N4431 §5.18/1]

В предположении, что в вашем случае вычисление значения левой стороны (включая просто доступ к члену, а не чтение) не вызывает поведение undefined, я бы применил вышеописанное:

  • Вычисление значения правой стороны читает u.f, который является активным членом объединения. Так что все хорошо.
  • Выполняется назначение. Это включает в себя запись полученного результата в u.i, который теперь изменяет активный член объединения.

Ответ 2

Неактивные участники могут быть записаны. Это на самом деле единственный способ сделать их активными. Активный участник не имеет ограничений; его можно прочитать и записать.

Вы можете принять адрес неактивного члена. Это действительный способ выполнить запись:

union {
  int i;
  float f;
} u;
float* pf = &u.f; // Does NOT change the active member.
u.i = 3;
*pf = 3.0; // Changes the active member.

В вашем примере активный член может стать только u.i, записав в него 5, что означает, что значение u.f должно быть прочитано.

Ответ 3

Изучая [class.union]/1, из соображений о стандартном союзе макета, содержащем стандартные союзы макета, разделяющие общую начальную последовательность, это означает, что следующее: ok

int main()
{
   union 
   {
      union 
      {
          int x ;
          float y ;
      } v ;
      union 
      {
          int x ;
          double z ;
      } w ;      
   } u ;

   u.v.x = 2 ;
   int n = u.w.x ; // n contains 2
}

Здесь общая начальная последовательность int x ;.

Это не совсем вопрос, но говорит нам, что этот вид смеси в порядке.