Delphi: Loop through bytes in record
Asked Answered
R

2

7

I have a record that contains multiple bytes/arrays of bytes:

  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;

I have a single record of this type and I need to loop over the bytes inside (to create a simple checksum by adding each byte to the checksum). Is there a simple way to do this in a loop or will I need to go over each element inside the record individually?

Repudiation answered 11/2, 2013 at 9:45 Comment(0)
I
10

You can do something like:

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;

In this particular case, it will work correctly, because all fields in TRdmPacket are bytes or arrays of bytes and they are not aligned. Read further how Packed and $Align directive affects internal record layout in case you want to use this method for other type of records.

Inchmeal answered 11/2, 2013 at 9:48 Comment(2)
As it happens, every field in this record has alignment 1 and so its layout will be the same as if it were packed. You do make a very good point regarding alignment, that's critical here.Pavonine
Alignment does not matter if all fields are bytes or byte arraysChaunce
C
3

You can use the absolute directive for this

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;
Confab answered 11/2, 2013 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.