2015-08-05 26 views
13

Questo codice è ben definito?Assegnazione tra membri del sindacato

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

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

accede due diversi membri del sindacato in un'espressione così mi chiedo se cade fallo dei [class.union]/1 Disposizioni circa membro attivo di un sindacato.

Lo standard C++ sembra sottodescrivare quali operazioni modificano il membro attivo per i tipi built-in e cosa succede se un membro inattivo viene letto o scritto.

+0

Non il secondo compito renderebbe 'u.i' il membro attivo e' u.f' un membro inattivo? –

+1

No: se una funzione viene dichiarata per restituire un valore, ma non lo fa, è un comportamento indefinito (scherzo, presumo tu stia parlando dell'assegnazione 'union'). – Tas

+2

Direi che, poiché il calcolo del valore di 'u.f' è sequenziato prima dell'effetto collaterale dell'assegnazione, in nessun momento nel tempo è ambiguo quale membro è attivo e in nessun momento nel tempo viene letto un membro inattivo. L'istruzione in questione dovrebbe comportarsi come 'auto temp = u.f; ui = temp; ' –

risposta

-2

Osservando [class.union]/1, dalle considerazioni circa sindacati layout standard contenenti sindacati layout standard che condividono una sequenza iniziale comune, vuol dire che la segue è 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 
} 

Qui la sequenza iniziale comune è int x ;.

Questa non è esattamente la domanda, ma ci dice che questo tipo di mix è OK.

+1

'Una struttura di layout standard è una classe di layout standard definita con la struct della chiave di classe o la classe key class. la garanzia della sequenza iniziale non si applica a 'union's – user657267

4

I membri inattivi possono essere scritti su. Questo è in effetti l'unico modo per renderli attivi. Il membro attivo non ha restrizioni; può essere letto e scritto

È possibile prendere l'indirizzo di un membro inattivo. Questo è un modo valido per eseguire la scrittura:

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. 

Nel tuo esempio, il membro attivo può solo diventare u.i scrivendo 5 ad esso, il che significa che il valore u.f deve essere stato letto.

+0

Ciò presuppone che la lettura e la scrittura avvengano in modo sequenziato; in particolare, presuppone che la valutazione del rhs sia sequenziata, prima della scrittura del lhs. Credo che sia vero: vero? – Yakk

+0

Alcune persone dicono che questo vìola il rigoroso aliasing. Un'idea pazza se me lo chiedi, ma lavorano su GCC ... – curiousguy

+0

@curiousguy: quale parte precisa? Il GCC si lamenta giustamente della lettura ** attraverso un altro tipo. Logico, perché non cambia il membro attivo ed è una violazione del tipo (leggendo un membro non attivo). – MSalters

6

L'operatore di assegnazione (=) e gli operatori di assegnazione composti si raggruppano tutti da destra a sinistra. [...] In tutti i casi, l'assegnazione viene sequenziata dopo il valore calcolo degli operandi di destra e di sinistra e prima del calcolo del valore dell'espressione di assegnazione. [...]

[N4431 §5.18/1]

Sotto la premessa che nel tuo caso il valore calcolo del lato sinistro (che coinvolge solo un accesso utente, non è una lettura) fa non causa un comportamento indefinito, mi piacerebbe applicare quanto sopra come segue:

  1. il valore di calcolo del lato destro si legge u.f, che è il membro attivo del sindacato. Quindi tutto è buono.
  2. L'assegnazione viene eseguita. Ciò comporta la scrittura del risultato ottenuto a u.i, che ora modifica il membro attivo dell'unione.
+0

Ma il lato sinistro 'u.i' viene valutato prima dell'assegnazione, quando il membro attivo è ancora' u.f'. La formulazione dei sindacati non è chiara. – curiousguy

+1

La formulazione è davvero poco chiara. Ma penso che sia solo indefinito se si legge da un membro inattivo, e che la valutazione della parte sinistra non implica la lettura di 'u.i'. –

Problemi correlati