2013-02-11 11 views
6

mam rekord, który zawiera wiele bajtów/tablice bajtów:Delphi: Pętla przez bajtów w rekordzie

type 
    TRdmPacket = record 
    sc: byte; 
    subSc: byte; 
    msgLength: byte; 
    destUID: array[0..5] of byte; 
    srcUID: array[0..5] of byte; 
    transNum: byte; 
    portID: byte; 
    msgCount: byte; 
    subDevice: array[0..1] of byte; 
    cc: byte; 
    pid: array[0..1] of byte; 
    pdl: byte; 
    end; 

Mam pojedynczy rekord tego typu i muszę pętli ciągu bajtów wewnątrz (w celu utworzenia prosta suma kontrolna, dodając każdy bajt do sumy kontrolnej). Czy istnieje prosty sposób na zrobienie tego w pętli, czy też będę musiał przejść indywidualnie każdy element wewnątrz rekordu?

Odpowiedz

8

można zrobić coś takiego:

var 
    sum: Byte; 
    ptr: PByte; 
    i: Integer; 
begin 
    sum := 0; 
    ptr := PByte(@rdmPacket); 

    for i := 0 to SizeOf(TRdmPacket) - 1 do 
    begin 
    sum := sum xor ptr^; 
    Inc(ptr); 
    end; 
end; 

w tym konkretnym przypadku, to będzie działać poprawnie, ponieważ wszystkie pola w TRdmPacket są bajtów lub tablice bajtów i nie są wyrównane. Przeczytaj dalej, w jaki sposób Packed i $Align directive wpływa na wewnętrzny układ rekordów, na wypadek gdybyś chciał użyć tej metody dla innych typów rekordów.

+1

Jak to się dzieje, każde pole w tym rekordzie ma alignment 1 a więc jego układ będzie taki sam, jak gdyby były zapakowane. Zrobisz bardzo dobry punkt w odniesieniu do wyrównania, to jest tutaj bardzo ważne. –

+0

Wyrównanie nie ma znaczenia, jeśli wszystkie pola są bajtami lub tablicami bajtów – kludg

+0

Świetnie się spisało, dzięki za naprawdę szybką pomoc. – user2060821

2

Można użyć do tego absolutną dyrektywę

type 
    TRdmPacket = record 
    sc: byte; 
    subSc: byte; 
    msgLength: byte; 
    destUID: array[0..5] of byte; 
    srcUID: array[0..5] of byte; 
    transNum: byte; 
    portID: byte; 
    msgCount: byte; 
    subDevice: array[0..1] of byte; 
    cc: byte; 
    pid: array[0..1] of byte; 
    pdl: byte; 
    end; 

Function GetPackChecksum(pack:TRdmPacket):Integer; 
var 
BArray:Array [0..SizeOf(TRdmPacket) - 1] of Byte absolute pack; 
i:Integer; 
begin 
Result := 0; 
for I := Low (BArray)to High(BArray) do 
    begin 
     Result := Result + BArray[i]; 
    end; 

end; 

procedure TForm2.Button1Click(Sender: TObject); 
var 
pack:TRdmPacket; 
begin 
    ZeroMemory(@pack,SizeOf(Pack)); 
    pack.sc := 100; 
    pack.destUID[1] := 123; 
    Showmessage(IntToStr(GetPackChecksum(pack))); 
end;