2012-03-21 4 views
8

mam następny kod:Dlaczego rozmiar rekordu nie jest równy sumie rozmiarów jego pól?

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; 

Program pokazuje następujący komunikat:

128+6=136 

Dlaczego SizeOf(TRecord3) równa 136 zamiast 134?

+0

Zasada: jeśli planujesz użyć niektórych struktur z plikami - zadeklaruj je jako "spakowane". – OnTheFly

+2

Moja zasada nigdy nie byłaby zapisywaniem binarnych reprezentacji rekordów do pliku –

+0

. Tak, unikaj przechowywania danych binarnych, ale dyrektywa pakowana ma swoje zastosowania, gdy rekordy są przekazywane podczas operacji we/wy (biblioteka dll, komunikacja szeregowa itp.). Jednak przy opracowywaniu nowego oprogramowania należy zastosować standardowe techniki konwersji binarnej/łańcuchowej. –

Odpowiedz

15

Jest to spowodowane dopełnieniem dodanym z powodu wyrównania rekordu. TRecord3 ma wyrównanie 4, ponieważ zawiera wartości single. I tak dopełnienie jest dodawane na końcu rekordu, aby rozmiar był dokładną wielokrotnością 4. Dlatego rozmiar ma wartość 136, a nie wartość 134, której oczekiwałeś.

Możesz zadeklarować swój rekord jako packed lub, równoważnie, ustawić opcję kompilatora wyrównania na $ALIGN 1. Przy wyrównaniu 1 nie będzie padding dodany do rekordu i SizeOf(TRecord3)=134. Jednak zdecydowanie nie należy tego robić. Korzystanie z naturalnego wyrównania zapewnia najbardziej wydajny dostęp do pamięci dla rekordów. Na przykład procesor ładuje droższą wartość niż ładowanie wyrównanej wartości. W przypadku modelu single lub integer naturalne wyrównanie dotyczy 4-bajtowego ograniczenia. W przypadku double naturalne wyrównanie jest na granicy 8-bajtowej i tak dalej. Powinieneś używać zapakowanych rekordów, jeśli potrzebujesz kompatybilności binarnej z inną biblioteką, która używa zapakowanych rekordów.

+2

ponadto można zmienić deklarację na "typ TRecord3 = zapakowany rekord ...", aby zapobiec wyrównaniu rekordów, chociaż zazwyczaj nie jest to konieczne. Wyrównane rekordy działają lepiej, ale w niektórych przypadkach możesz potrzebować zapakowanych rekordów. – GolezTrol

4

Jest to spowodowane wyrównaniem. Pola w rekordzie są wyrównane do 4 bajtów lub 8 bajtów (lub bajtów, gdy w rekordzie używane są tylko bajty) w taki sposób, aby rekord w tablicy wszystkich pól był wyrównany. Jeśli chcesz, aby formuła działała, powinieneś użyć "zapakowanego rekordu". Należy pamiętać, że pola mogą być niewyrównane i mogą utrudnić działanie.