2012-03-21 10 views
8

Ho codice seguente:Perché la dimensione di un record non è uguale alla somma delle dimensioni dei suoi campi?

type TRecord1 = record 
    myarr: array [0..31] of single: 
end; 
type TRecord2 = record 
    b1, b2, b3, b4, b5, b6: byte; 
end; 
type TRecord3 = record 
    myarr: array [0..31] of single:  
    b1, b2, b3, b4, b5, b6: byte; 
end; 

procedure TForm1.FormCreate(Sender: Tobject); 
begin 
    ShowMessage(IntToStr(SizeOf(TRecord1))+'+'+IntToStr(SizeOf(TRecord2))+ 
     '='+IntToStr(SizeOf(TRecord3))); 
end; 

Il programma mostra il seguente messaggio:

128+6=136 

Perché è SizeOf(TRecord3) uguale a 136 invece di 134?

+0

regola pratica: se si prevede di utilizzare alcune strutture con i file, dichiararli come 'imballati'. – OnTheFly

+2

La mia regola empirica non sarebbe mai scrivere le rappresentazioni binarie dei record sul file –

+0

Sì, evita di memorizzare dati binari, ma la direttiva compressa ha i suoi usi quando i record vengono passati durante I/O (dll, comunicazione seriale ecc.). Tuttavia, l'uso di tecniche di conversione binario/stringa standardizzate dovrebbe essere applicato a nuovi sviluppi. –

risposta

15

Ciò è dovuto al riempimento aggiunto a causa dell'allineamento dei record. TRecord3 ha allineamento di 4 poiché contiene valori single. E così il padding viene aggiunto alla fine del record per rendere la dimensione un multiplo esatto di 4. Ecco perché la dimensione è 136 anziché il valore di 134 che ti aspettavi.

È possibile dichiarare il record come packed o, in modo equivalente, impostare l'opzione del compilatore di allineamento su $ALIGN 1. Con un allineamento di 1 non sarà aggiunto alcun padding al record e SizeOf(TRecord3)=134. Tuttavia, ti consiglio vivamente di non farlo. Utilizzando l'allineamento naturale si ottiene l'accesso alla memoria più efficiente per i record. Ad esempio, è più costoso per il processore caricare un valore disallineato rispetto al caricamento di un valore allineato. Per un single o un integer, l'allineamento naturale è su un limite di 4 byte. Per un double l'allineamento naturale è su un limite di 8 byte e così via. È necessario utilizzare i record compressi se è necessaria la compatibilità binaria con un'altra libreria che utilizza i record compressi.

+2

inoltre, è possibile modificare la dichiarazione in "tipo TRecord3 = record compresso ..." per impedire l'allineamento dei record, anche se in genere non è necessario. I record allineati hanno un rendimento migliore, ma in alcuni casi potrebbero essere necessari record compressi. – GolezTrol

4

Ciò è dovuto all'allineamento. I campi nel record sono allineati su 4 byte o 8 byte (o byte quando nel record sono usati solo byte). In modo tale che il record quando in un array tutti i campi continueranno ad essere allineati. Se vuoi che la formula funzioni, dovresti usare un "record compresso". Si noti che i campi potrebbero essere non allineati e potrebbero ostacolare le prestazioni.

Problemi correlati