2013-02-11 39 views
6

Tôi có một kỷ lục có chứa nhiều byte/mảng byte:Delphi: Vòng qua byte trong hồ sơ

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; 

Tôi có một hồ sơ duy nhất thuộc loại này và tôi cần để lặp qua các byte bên (để tạo một kiểm tra đơn giản bằng cách thêm từng byte vào tổng kiểm tra). Có một cách đơn giản để làm điều này trong một vòng lặp hoặc tôi sẽ cần phải đi qua từng yếu tố bên trong hồ sơ cá nhân?

Trả lời

8

Bạn có thể làm một cái gì đó như:

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; 

Trong trường hợp này, nó sẽ làm việc một cách chính xác, bởi vì tất cả các lĩnh vực trong TRdmPacket là byte hoặc mảng byte và họ không thẳng hàng. Đọc thêm cách Packed$Align directive ảnh hưởng đến bố cục bản ghi nội bộ trong trường hợp bạn muốn sử dụng phương pháp này cho các loại bản ghi khác.

+1

Vì nó xảy ra, mọi lĩnh vực trong hồ sơ này có sự liên kết 1 và do đó bố trí của nó sẽ giống như thể nó đã được đóng gói. Bạn làm cho một điểm rất tốt về sự liên kết, đó là quan trọng ở đây. –

+0

Căn chỉnh không quan trọng nếu tất cả các trường là byte hoặc mảng byte – kludg

+0

Làm việc tuyệt vời, cảm ơn sự trợ giúp thực sự nhanh chóng. – user2060821

2

Bạn có thể sử dụng các chỉ thị tuyệt đối cho điều này

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;