2013-01-24 15 views
5

Durante il tentativo di eseguire il debug di un problema che sto avendo con Speex, ho notato che (bene, non solo Speex, ma qualche esempio di codice pure) effettua le seguenti operazioni:Lancia una struct T * a una struct C * comportamento non definito, se il primo campo di T è un C?

  • Ritorna un puntatore a EncState da un funzione di inizializzazione
  • Cast che puntatore a un puntatore nullo
  • Conservare il puntatore nullo
  • (altrove)
  • cast del puntatore nullo a un puntatore a puntatore a SpeexMode
  • dereference il puntatore

Accade così che la definizione di EncState inizia con un campo di tipo SpeexMode *, e quindi i valori interi di un puntatore al primo campo e un puntatore alla struttura capita di essere la stessa . Il dereferenziamento funziona in runtime.

Ma ... la lingua effettivamente lo consente? Il compilatore è libero di fare ciò che vuole se lo compila? Lanciare una struct T * a una struct C * comportamento non definito, se il primo campo di T è un C?

+0

Anche un duplicato di [Compatibilità puntatore Struct] (http://stackoverflow.com/questions/8702713/struct-pointer-compatibility) – netcoder

+0

È tecnicamente UB, sì, a causa della rigorosa regola di aliasing. Il modo preferito è di solito usare un'unione con membri di entrambi i tipi. – netcoder

risposta

7

Dalla serie C11:

(C11 §6.7.2.1.15: "Un puntatore a un oggetto struttura, opportunamente convertito, indica suo membro iniziale ... e viceversa ci possono. essere imbottitura senza nome all'interno come oggetto la struttura, ma non al suo inizio . ")

il che significa che il comportamento che si vede è consentito e garantito.

+1

Rompe però la regola di aliasing. – netcoder

+0

@netcoder Vero, se porta a problemi in questo caso non è chiaro però. – pmr

+0

+1 Risposta concisa e chiara ... Potrei aggiungere come commento che puoi trovare molti molti esempi di questo tipo di typecasting nel framework GObject – Rerito