我遇到逻辑问题。我不知道如何将记录复制到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数组?如何?如果有,
这种逻辑会起作用吗?
答案 0 :(得分:7)
CopyMemory(@a, @b, SizeOf(TypeB))
如果a
的类型为TypeA
而b
的类型为TypeB
。
答案 1 :(得分:5)
变体记录:
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
答案 2 :(得分:3)
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;
答案 3 :(得分:3)
将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
答案 4 :(得分:3)
所有其他答案都是直接复制内存的变体,但我认为这是错误的方法。它是低级别的,你使用的是高级语言,很容易出错如果您的记录包含托管数据类型,则存在风险。
如果您尝试获取记录的一个元素的前两个字节,请尝试使用变体记录(在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
令人困惑 - 它实际上并不是机器的'字大小',it's 16 bits。packed record
',justification for this is... iffy。答案 5 :(得分:2)
您可以通过以下方式省略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;
答案 6 :(得分:0)
如果您只想将字节从一个地方复制到另一个地方,请使用MOVE而不是CopyMemory。
要获取记录的大小,请使用SizeOf而不是Length。