[英]Delphi Memory copy with Record to another Record
我遇到邏輯問題。 我不知道如何將記錄復制到Delphi中的另一條記錄。
TypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = record
b1 : byte;
b2 : byte;
end;
我有兩個記錄TypeA和TypeB。 例如,我發現TypeA記錄中的數據屬於TypeB記錄。 注意:TypeA具有更長的數據長度。
問題:如何復制TypeA內存並將其放在TypeB記錄中?
CopyMemory(@TypeA, @TypeB, Length(TypeB))
當我嘗試CopyMemory並得到一個錯誤(無法比較的類型) 。
PS:我不想像下面那樣復制或分配它。
TypeB.b1:= TypeA.value1 && $ FF;
TypeA和TypeB只是示例記錄。 大多數情況下,記錄TypeA和TypeB可能包含多個記錄,並且分配表單TypeA並分配給TypeB記錄將更加困難。
提前致謝
----加法問題:
有沒有辦法將Delphi記錄復制到Byte數組以及如何? 如果有,
這個邏輯會起作用嗎?
CopyMemory(@a, @b, SizeOf(TypeB))
如果a
是TypeA
類型而b
是TypeB
類型。
變體記錄:
TypeA = packed record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = packed record
b1 : byte;
b2 : byte;
end;
TypeAB = packed record
case boolean of
false:(a:TypeA);
true:(b:TypeB);
end;
..
..
var someRec:TypeAB;
anotherRec:TypeAB;
..
..
anotherRec.b:=someRec.b
procedure CopyAtoB( const A: TypeA; var B: TypeB);
begin
// Assume A is bigger than B.
Move( A, B, SizeOf( TypeB))
end;
或(用數學單位)
procedure CopyAtoB( const A: TypeA; var B: TypeB);
begin
// No assumptions about A, B sizes.
FillChar( B, SizeOf( B), 0);
Move( A, B, Min( SizeOf( TypeA), SizeOf( TypeB)))
end;
將A記錄復制到B記錄有一個很好的方法 - 運算符重載; 在這種情況下,您可以簡單地重載Implicit和Explicit操作並編寫代碼,如b := a
:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils;
type
TTypeA = record
value1 : integer;
value2 : integer;
value3 : integer;
end;
TTypeB = record
b1 : byte;
b2 : byte;
class operator Implicit(value : TTypeA):TTypeB;
end;
class operator TTypeB.Implicit(value: TTypeA): TTypeB;
begin
result.b1 := Hi(value.value1);
result.b2 := Lo(value.value1);
end;
var a : TTypeA;
b : TTypeB;
begin
b := a;
end.
您可以使用TBytesStream將記錄復制到字節數組:
var a : TTypeA;
bs : TBytesStream;
bArr : TArray<byte>;//array of byte;
begin
bs := TBytesStream.Create();
bs.Write(a, sizeof(a));
bArr := bs.Bytes;
end;
或者只是將字節數組的大小設置為sizeof(A)
然后再設置copyMemory
所有其他答案都是直接復制內存的變體,但我認為這是錯誤的方法。 它是低級的,您使用的是高級語言,很容易出錯,如果您的記錄包含托管數據類型,則存在風險。
如果你想要獲取記錄的一個元素的前兩個字節,請嘗試使用變體記錄 (在C中,一個聯合。)它是一個記錄的一部分,可以通過多種方式解決,在這里你想要將其作為一個字或一系列字節來處理。
嘗試這樣的事情(未經測試,只需在SO編輯器中輸入):
type
TTwoBytes : packed record
ByteA, ByteB : Byte;
end;
TValueRecord : packed record:
case Boolean of
True: (Value: SmallInt);
False: (ValueBytes : TTwoBytes);
end;
end;
TMyRecord = packed record
Value1, Value2, Value3 : TValueRecord;
end;
然后代碼:
var
MyRecord: TMyRecord;
MyBytes: TTwoBytes;
begin
MyRecord := ...; // Fill it with data here
// Access the words / smallints by something like: MyRecord.Value1.Value
MyBytes := MyRecord.ValueBytes; // The key bit: type safe assignment
// Do something with MyBytes.ByteA or MyBytes.ByteB
end;
這給你帶來什么比直接復制內存更好?
case ... of
'語法'是愚蠢的,但這是另一個討論......: )) 一些說明:
Word
更改為SmallInt
因為我發現Word
令人困惑 - 它實際上並不是機器的'字大小', 而是16位 。 packed record
',其理由是... iffy 。 您可以通過以下方式省略CopyMemory()(Windows單位)使用:
type
PTypeA = ^TTypeA;
TTypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
PTypeB = ^TTypeB;
TTypeB = record
b1 : byte;
b2 : byte;
end;
var
A: TTypeA = (value1 : 11; value2 : 22; value3 : 33);
B: TTypeB;
B1: TTypeB;
C: {packed?} array of Byte;
begin
Assert(SizeOf(TTypeA) >= SizeOf(TTypeB));
//...
B:= PTypeB(@A)^;
//...
SetLength(C, SizeOf(A));
// TTypeA record to Byte Array
PTypeA(@C[0])^:= A;
// Byte Array to TTypeB
B1:= PTypeB(@C[0])^
end;
如果您只想將字節從一個地方復制到另一個地方,請使用MOVE而不是CopyMemory。
要獲得記錄的大小,請使用SizeOf而不是Length。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.