[英]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.