Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi内存将记录复制到另一个记录_Delphi_Memory_Copy_Record - Fatal编程技术网

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

我在逻辑上有问题。我不知道如何在Delphi中将记录复制到另一个记录

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
    ”,即

你的问题毫无意义。你想把一张唱片的一半复制到另一张唱片上?您可能需要将多个半记录复制到多个其他记录中?你需要澄清你的问题,因为现在它看起来很奇怪(而且无法回答,因为它不清楚你想做什么)。谢谢你的评论。我自己也不清楚如何得到逻辑。我得到的信息是A型记录数据属于B型记录数据。放错地方了。我想恢复数据并将其保存在TypeB中。尝试
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;