Delphi内存将记录复制到另一个记录
我在逻辑上有问题。我不知道如何在Delphi中将记录复制到另一个记录Delphi内存将记录复制到另一个记录,delphi,memory,copy,record,Delphi,Memory,Copy,Record,我在逻辑上有问题。我不知道如何在Delphi中将记录复制到另一个记录 TypeA = record value1 : word; value2 : word; value3 : word; end; TypeB = record b1 : byte; b2 : byte; end; 我有两张A型和B型的唱片。例如,我发现TypeA记录中的数据属于TypeB记录注意:TypeA的数据长度较长。 问题:如何复制TypeA内存并将其放入TypeB记录中? Cop
TypeA = record
value1 : word;
value2 : word;
value3 : word;
end;
TypeB = record
b1 : byte;
b2 : byte;
end;
我有两张A型和B型的唱片。例如,我发现TypeA记录中的数据属于TypeB记录注意:TypeA的数据长度较长。
问题:如何复制TypeA内存并将其放入TypeB记录中?
CopyMemory(@TypeA, @TypeB, Length(TypeB))
当我尝试CopyMemory时,出现了一个错误(不兼容的类型)
PS:我不想像下面那样复制或分配它。
类型B.b1:=类型A.value1和$FF
TypeA和TypeB只是示例记录。大多数情况下,记录类型A和类型B可能包含多个记录,并且
将更难分配表格TypeA和分配给TypeB记录
提前谢谢
----补充问题:
有没有一种方法可以将Delphi记录复制到字节数组,以及如何复制?如果有,
- 键入记录到字节数组
- 类型B的字节数组
这个逻辑行得通吗?如果您想简单地将字节从一个地方复制到另一个地方,请使用MOVE而不是CopyMemory 要获得记录的大小,请使用SizeOf而不是Length
CopyMemory(@a, @b, SizeOf(TypeB))
如果a
属于a
类型,而b
属于b
类型
procedure CopyAtoB( const A: TypeA; var B: TypeB);
begin
// Assume A is bigger than B.
Move( A, B, SizeOf( TypeB))
end;
或(带数学单元)
您可以通过以下方式忽略CopyMemory()(Windows单元)的使用:
将A记录复制到B记录有一个很好的方法-运算符重载;在这种情况下,您可以简单地重载隐式和显式操作,并编写类似
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.
您可以使用TByteStream将记录复制到字节数组:
var a : TTypeA;
bs : TBytesStream;
bArr : TArray<byte>;//array of byte;
begin
bs := TBytesStream.Create();
bs.Write(a, sizeof(a));
bArr := bs.Bytes;
end;
var a:t类型a;
bs:tbytestream;
巴尔:塔雷//字节数组;
开始
bs:=tbytestream.Create();
写(a,sizeof(a));
bArr:=bs.字节;
结束;
或者只需将字节数组的大小设置为sizeof(A)
,然后copyMemory
变量记录:
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
所有其他答案都是直接复制内存的变体,但我认为这是错误的方法。这是低级的,而且您使用的是高级语言,很容易出错,如果您的记录包含托管数据类型,则会有风险 如果您试图获取记录中一个元素的前两个字节,请尝试使用变体记录(在C中为联合)。它是记录的一部分,可以通过多种方式进行寻址,在这里您希望将其作为字或一系列字节进行寻址 尝试以下操作(未经测试,仅在SO编辑器中键入): 那么对于代码:
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;
这比直接复制内存有什么好处?
CopyMemory(@TypeA, @TypeB, Length(TypeB))
- 它是安全的:如果您有更复杂的包含字符串、接口等的记录,它仍然可以工作,而不会破坏引用计数
- 它是类型安全的:不直接复制内存:您和编译器都知道您拥有和正在使用的内容
- 这是规范的:这可能是“德尔菲方法”。(虽然有几种方法可以组织记录-如果你查看答案历史记录,我原来有一种更糟糕的方法。此外,我认为'的'语法很愚蠢,但这是另一种讨论…))
- 我将您的
更改为Word
,因为我发现SmallInt
令人困惑-这实际上不是机器的“字号”Word
- 我想也是
- 我使用了“
”,即packed record
Move()
而不是CopyMemory()
例如:Move(TypeA,TypeB,SizeOf(TypeB))代码>@Remy:为什么?MoveMemory
和CopyMemory
都实现为Move(源^,目标^,长度)代码>您有两个问题。您正在尝试获取类型的地址。您需要声明一些变量。您需要使用sizeof而不是length。MoveMemory
和CopyMemory
都实现为Move(Source^,Destination^,length)
MoveMemory()
和CopyMemory()
需要Windows
单元,这是特定于平台的Move()
位于系统的单元中,可在所有平台上使用。我对此进行了改进,但如果有一些解释会更好。否则它看起来就像魔术一样。它还需要一个警告:如果TypeB
包含任何托管类型的字段,这会干扰Delphi的使用计数器,并可能导致无法跟踪的AV
,“所有其他答案都是直接复制内存的变体”-不,不是@马丁·詹姆斯:现在不是,但当我开始写这篇文章的时候是:)该死,我想你比我先进来。我发布了一个类似的答案:)我喜欢这个-比下面使用变体记录的答案更现代的Delphi。
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;