2012-11-08 9 views
8

Eventuali duplicati:
Aliasing `T*` with `char*` is allowed. Is it also allowed the other way around?È questo l'uso del comportamento non definito di std :: array?

sto usando un std::array di char s per contenere un valore di tipo sconosciuto primitiva, che è lunga non più di 10 byte, in questo modo:

std::array<char, 10> val; 
*reinterpret_cast<double*>(val.data()) = 6.3; 
//blah blah blah... 
double stuff = *reinterpret_cast<double*>(val.data()); 

ho letto che la fusione avanti e indietro attraverso char * non è u ndefinito, poiché il compilatore presuppone che uno char * possa alias un valore di qualsiasi tipo. Funziona ancora quando viene inserito il valore (cosa presumo che sia) un array di char s all'interno dell'oggetto?

Nota: sono consapevole che potrei utilizzare un sindacato qui, ma ciò comporterebbe una grande quantità di codice boilerplate per quello che sto facendo, e vorrei evitarlo se necessario, da qui la domanda.

+0

Domanda diversa, stessa risposta. – Dan

+0

Stessa domanda, parole diverse. ; -] – ildjarn

risposta

13

Sì, std::array< char, 10 > non soddisfa i requisiti di allineamento di double in modo che reinterpret_cast provochi UB.

Prova std::aligned_storage invece.

+0

Allineamento! Certo, è qualcosa che non mi è nemmeno venuto in mente. Grazie per questo link, è esattamente ciò di cui avevo bisogno. – Dan

0

Non importa ciò che la matrice è contenuto in.

La norma non ha nemmeno prendere in considerazione ciò che circonda qualcosa (è così semplice), ma non la conversione di supporto per/da char sequenze.

Per fare ciò direttamente tramite reinterpret_cast e assegnazione, è necessario che il buffer sia allineato correttamente.

Un'alternativa è utilizzare memcpy, che non interessa l'allineamento.

Su un problema correlato, non è generalmente una buona idea scendere al livello binario. Ad esempio, una semplice modifica della versione del compilatore potrebbe rendere inaccessibile un file di dati serializzati in modo binario. Un driver principale per fare ciò è comunque considerazioni sulle prestazioni non elaborate.

+0

Supporta la conversione di un arbitrario 'char *' in 'double *'? Penso che la conversione del puntatore potrebbe essere una perdita. Considera un ABI con puntatori di dimensioni diverse. – Potatoswatter

+0

Che tipo di modifica del compilatore potrebbe causare che ciò accada? – Dan

+0

Un puntatore 'char' ha una risoluzione di indirizzamento a grana fine come qualsiasi puntatore, come con' void'. La conversione del puntatore può essere potenzialmente perdita se il buffer non è allineato correttamente. In ogni caso la copia dei dati può essere * inefficiente *. –