读取和分配void类型参数

时间:2009-07-08 20:56:01

标签: delphi parameters void

我用void类型参数写了两个方法:

procedure Method1(const MyVar; size: cardinal);
var
  Arr: array of byte;
begin
  SetLength(Arr, size);
  {now copy the data from MyVar to Arr, but how?}  
end;

procedure Method2(var MyVar; size: cardinal);
var
  Arr: array of byte;
begin
  SetLength(Arr, size);
  {return the data from the array, but how?}
end;

在第一个中,我想将MyVar作为一个byte数组访问。在第二个中,我想将数据从本地数组Arr复制到MyVar。因此我使用了CopyMemory()函数,但它有些问题。

如果我在第二种方法中使用以下内容,只要调用Method2并将数组作为参数(Method2(指针(MyString)^,长度(MyString))或Method2(指针(MyArray)),就可以了,长度(MYARRAY)))。

CopyMemory(Pointer(MyVar), Pointer(Arr), size);

如果我用一个整数参数(Method2(MyInteger,SizeOf(MyInteger)))调用Method2,它就无法正常工作。在这种情况下,必须以这种方式调用CopyMemory():

CopyMemory(@MyVar, Pointer(Arr), size);

如何正确地从Method2返回数据,而不知道它是简单类型(或记录)还是数组? Method1中的情况类似,但在这里我必须使用

CopyMemory(Pointer(Arr), Pointer(MyVar), size);

如果是数组和

CopyMemory(Pointer(Arr), @MyVar, size);

如果是简单类型。

当我不知道MyVar参数是什么时,我该怎么办?

2 个答案:

答案 0 :(得分:6)

在Delphi中没有这样的虚空类型。你所指的是untyped parameter

无类型参数始终是实际的东西,而不是指向您应该使用的东西的指针。因此,将CopyMemory与此类参数一起使用的正确方法是将@运算符应用于此,如下所示:

CopyMemory(@MyVar, @Arr[0], size);

注意我也改变了传递第二个参数的方式。如果你不依赖于动态数组实际上是指向第一个元素的指针的事实,那就更好了。如果你需要一个指向第一个元素的指针,那就明确说出来,就像我在这里做的那样。

您的混淆来自于您使用参数进行的测试,就好像它是一个指针一样,测试似乎有效。不过,我怀疑该测试的有效性。当你说Pointer(MyString)^时,你所拥有的是字符串的第一个字符。当你在函数内部说Pointer(MyVar)时,你将该字符输入到指针中,这是一个无效的类型转换。如果你的程序似乎工作,那只是偶然的;你的代码错了。

我能给出的最好的建议是不要输入内容,除非你真的需要。当你这样做时,请确保你输入的东西真的有那种类型。在您的情况下,在将其作为无类型参数传递之前,您不需要输入任何内容。您可以像这样致电Method1

Method1(MyString[1], Length(MyString) * Sizeof(Char));

(我乘以SizeOf(Char),因为我不知道你是否有Delphi 2009.)

另外,请避免使用无类型参数。编译器可以帮助确保程序正确性的一个好处是强制类型安全,但是当你拿走类型时,编译器就无法帮助你了。

答案 1 :(得分:4)

您的问题是您将数据或指针传递给Method1 / 2。您应该始终传递数据。 可能你只是忘了动态数组是一个指针本身?你不应该在你的方法中传递A或指针(A)(这里的A是动态数组)。传递A [0]或指针(A)^。

procedure Method1(const MyVar; size: cardinal);
var
  Arr: array of byte;
begin
  SetLength(Arr, size);
  CopyMemory(Pointer(Arr), @MyVar, Size);
end;

procedure Method2(var MyVar; size: cardinal);
var
  Arr: array of byte;
begin
  SetLength(Arr, size);
  Arr[0] := 1;
  Arr[1] := 2;
  Arr[2] := 3;
  Arr[3] := 4;
  CopyMemory(@MyVar, Pointer(Arr), Size);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  A: array of Integer;
begin
  I := $01020304;
  Method1(I, 4); // we pass data itself, not the pointer to it.
  Method2(I, 4);
  SetLength(A, 2);
  A[0] := 0;
  A[1] := $01020304;
  Method1(A[0], Length(A) * SizeOf(A[0])); // note, that we pass data, not pointer
  Method2(A[0], Length(A) * SizeOf(A[0])); // A or Pointer(A) is a pointer to array's data
end;

如果A是动态数组:

  1. A [0]与指针(A)^相同,表示数组的数据。
  2. @A [0]与指针(A)或A相同,表示数组本身,它是指向数据的指针(以及负偏移的一些技术信息)。
  3. 如果A是静态数组:

    1. A [0]与A相同,表示数组本身,即数组的数据。
    2. @A [0]与@A相同,表示指向数组的指针。
    3. 指针(A)或指针(A)^无意义。
    4. 注意,Method1 / 2中的Arr也是一个动态数组,这就是我们将它转​​换为指针的原因(CopyMemory询问指针,而不是数据)。如果我们想使用Move例程(询问数据),我们应该改写Pointer(A)^。

相关问题