[英]Delphi Memory copy with Record to another Record
I am having problem with the logic. 我遇到逻辑问题。 I have no idea how to copy record to another record in Delphi.
我不知道如何将记录复制到Delphi中的另一条记录。
TypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = record
b1 : byte;
b2 : byte;
end;
I have my two records TypeA and TypeB. 我有两个记录TypeA和TypeB。 For example, I found out that data in TypeA record is belong to TypeB records.
例如,我发现TypeA记录中的数据属于TypeB记录。 Note: TypeA has longer Data Length.
注意:TypeA具有更长的数据长度。
Question: How do i copy TypeA memory and place it in TypeB record? 问题:如何复制TypeA内存并将其放在TypeB记录中?
CopyMemory(@TypeA, @TypeB, Length(TypeB))
When i tried CopyMemory and got an error (Incompaible types) . 当我尝试CopyMemory并得到一个错误(无法比较的类型) 。
PS: I don't want to copy or assign it like below.
PS:我不想像下面那样复制或分配它。
TypeB.b1 := TypeA.value1 && $FF;
TypeB.b1:= TypeA.value1 && $ FF;
TypeA and TypeB are just example records.
TypeA和TypeB只是示例记录。 Most of thecases, record TypeA and TypeB may contain multple records and it will be harder to allocate form TypeA and assign to TypeB record.
大多数情况下,记录TypeA和TypeB可能包含多个记录,并且分配表单TypeA并分配给TypeB记录将更加困难。
Thanks in advance 提前致谢
----Addition question: ----加法问题:
Is there a way to copy Delphi record to Byte array and how? 有没有办法将Delphi记录复制到Byte数组以及如何? If there is,
如果有,
Will this logic work? 这个逻辑会起作用吗?
CopyMemory(@a, @b, SizeOf(TypeB))
如果a
是TypeA
类型而b
是TypeB
类型。
Variant records: 变体记录:
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;
or (with Math unit) 或(用数学单位)
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;
to copy A record to B record there is a good way - operator overloading; 将A记录复制到B记录有一个很好的方法 - 运算符重载; in this case you can simply overload Implicit and Explicit operations and write code like
b := a
: 在这种情况下,您可以简单地重载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.
you can use TBytesStream to copy record to byte array: 您可以使用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;
or simply set size of byte array to sizeof(A)
and then copyMemory
或者只是将字节数组的大小设置为
sizeof(A)
然后再设置copyMemory
All the other answers are variations of copying memory directly, but I think that is the wrong approach. 所有其他答案都是直接复制内存的变体,但我认为这是错误的方法。 It's low-level and you're using a high-level language, it's easy to make mistakes, and it is risky if your records contain managed data types.
它是低级的,您使用的是高级语言,很容易出错,如果您的记录包含托管数据类型,则存在风险。
If you're trying to get the first two bytes of one element of a record, try using a variant record (in C, a union.) It is a section of a record that can be addressed several ways, and here you want to address it either as a word or series of bytes. 如果你想要获取记录的一个元素的前两个字节,请尝试使用变体记录 (在C中,一个联合。)它是一个记录的一部分,可以通过多种方式解决,在这里你想要将其作为一个字或一系列字节来处理。
Try something like this (untested, just typed in the SO editor): 尝试这样的事情(未经测试,只需在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;
Then for code: 然后代码:
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;
What does this give you that's better than directly copying memory? 这给你带来什么比直接复制内存更好?
case ... of
' syntax for this is silly, but that's another discussion... :)) case ... of
'语法'是愚蠢的,但这是另一个讨论......: )) Some notes: 一些说明:
Word
to SmallInt
since I find Word
confusing - it's not actually the 'word size' of the machine, it's 16 bits . Word
更改为SmallInt
因为我发现Word
令人困惑 - 它实际上并不是机器的'字大小', 而是16位 。 packed record
', the justification for this is... iffy . packed record
',其理由是... iffy 。 You can omit CopyMemory() (Windows unit) use by: 您可以通过以下方式省略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;
Use MOVE instead of CopyMemory if you want to simply copy the bytes from one place to another. 如果您只想将字节从一个地方复制到另一个地方,请使用MOVE而不是CopyMemory。
And to get the size of a record use SizeOf instead of Length. 要获得记录的大小,请使用SizeOf而不是Length。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.