使用动态数组the Move程序,你需要通过第一个元素数组的。例如:
var
Source: Pointer;
SourceSize: Integer;
Destination: array of Byte;
SetLength(Destination, SourceSize);
Move(Source^, Destination[0], SourceSize);
另请注意,第二个参数取消引用指针。那是因为Move
采取value您正在复制的内容,而不是指向该值的指针。您正在复制指针指向的内容,因此这就是您需要传递给的内容Move
.
顺便说一句,如果Destination
也是一个静态数组。您说得对,这并不是 Delphi 2009 所特有的。一直到 Delphi 4 都是如此,当时引入了动态数组。和Move
也有过同样的奇怪无类型参数永远的语法。
不要分配自己的内存GetMem
然后进行类型转换,使编译器认为您拥有的是动态数组。It's not。动态数组具有普通字节缓冲区所没有的引用计数和长度字段,并且由于您无法控制编译器生成的用于访问假定的动态数组的所有代码,因此您的程序存在尝试访问的危险数据结构中不存在的数据。
您可以使 PSP 函数将其数据直接存储到动态数组中。下面是一些代码:
var
Output: array of Byte;
SetLength(Output, OutputLength.Value);
if SendPSPQuery(Char(DriveLetter[1]),
cbxQuery.Items.IndexOf(cbxQuery.Text),
@Output[0],
OutputLength.Value) = 0
then
之后无需释放内存;编译器插入代码来释放动态数组Output
超出范围并且没有对该数组的其他引用。此代码采用动态数组并将其传递,就像它是普通缓冲区一样。这有效并且安全,因为动态数组实际上是普通旧缓冲区的子类型。该函数将接受指向数组第一个元素的指针,并将该指针视为指向一堆字节的指针,因为这正是它的本质。该函数不需要知道程序用于动态数组簿记的那些字节附近恰好有其他内容。
如果您的数据位于缓冲区中并且您希望将该缓冲区视为it如果是数组,而不是将数据复制到单独的数据结构中,那么您有两个选择。
-
声明一个静态数组pointer,然后将缓冲区指针类型转换为该类型。这是经典技术,您可以在各处的代码中看到它的使用,尤其是 Delphi 4 之前的代码。例如:
type
PByteArray = ^TByteArray;
TByteArray = array[0..0] of Byte;
var
ByteArray: PByteArray;
ByteArray := PByteArray(Output);
for i := 0 to Pred(OutputLength.Value) do begin
{$R-}
edtString.Text := edtString.Text + Chr(ByteArray[i]);
{$R+}
end;
The $R
指令的目的是确保关闭该代码的范围检查,因为数组类型被声明为长度为 1。使用该大小声明数组的部分原因是作为一个线索,表明您实际上不应该声明一个该类型的变量。仅通过指针使用它。另一方面,如果您知道数据的合适最大大小是多少,则可以使用该大小来声明数组类型,然后可以保持范围检查处于打开状态。 (如果您通常禁用范围检查,那么您只是自找麻烦。)
-
将您的缓冲区声明为PByte
代替Pointer
然后使用Delphi的新功能(截至Delphi 2009)支持将任意指针类型视为数组指针。在以前的版本中,仅PChar
, PAnsiChar
, and PWideChar
支持这种语法。例如:
var
Output: PByte;
for i := 0 to Pred(OutputLength.Value) do begin
edtString.Text := edtString.Text + Chr(Output[i]);
end;
The $POINTERMATH
不需要编译器指令来启用此功能PByte
因为那个类型是declared在该指令生效期间。如果你想进行类似 C 的指针操作other指针类型,然后放置{$POINTERMATH ON}
在使用新扩展语法的代码之前。
最后一点,您不需要一次构建一个字符的字符串。这在两个方面都是浪费。首先,您正在构建大量字符串,每个字符串仅比前一个大两个字节。其次,由于您将字符串结果存储在编辑控件中,因此您也强制该控件的操作系统实现分配一堆新字符串。将您的数据放入one字符串,然后将其一次性全部附加到您的编辑控件中:
var
OutputString: AnsiString;
SetString(OutputString, PAnsiChar(Buffer), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;