Delphi 当参数类型为打开字符数组时,是否允许动态字符数组?

Delphi 当参数类型为打开字符数组时,是否允许动态字符数组?,delphi,dynamic-arrays,open-array-parameters,Delphi,Dynamic Arrays,Open Array Parameters,我看着他,开始做实验。我的发现很有趣 procedure Clear(AArray: array of Integer); var I: Integer; begin for I := Low(AArray) to High(AArray) do AArray[I] := 0; end; var MyArray: array of Integer; begin Clear(MyArray); end. 这个简单的小示例演示如何使用开放数组参数将动态数组传递给过程。它完

我看着他,开始做实验。我的发现很有趣

procedure Clear(AArray: array of Integer);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := 0;
end;

var
  MyArray: array of Integer;
begin
  Clear(MyArray);
end.
这个简单的小示例演示如何使用开放数组参数将动态数组传递给过程。它完全按照预期编译和运行

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
begin
  Clear(MyArray);
end.
这是几乎相同的代码,唯一的区别是它使用的是
Char
数组,而不是
Integer
。它不编译。相反,编译器会吐出:

 E2010 Incompatible types: 'Array' and 'Dynamic array'
为什么会这样


搜索了一会儿后,我发现了QC报告。我正在运行Delphi 2009,它仍在运行。

我认为原因是
字符数组
PChar
兼容,因为这段代码编译:

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
  P: PChar;
begin
  Clear(P^);
end.
这可能是出于历史原因。
希望或将在这方面提供更多的反馈


--jeroen

因为文档特别提到了与动态数组兼容的Char类型的开放数组参数,所以这应该是一个bug。发件人:

函数查找(字符数组):
整数
[…]
注意:[…] 上一个示例创建了一个函数 它接受任何字符元素数组, 包括(但不限于)动态 数组。[……]


您可以使用这种数组,定义自己的类型:

type
  TCharDynArray = array of char;

procedure Clear(AArray: TCharDynArray);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

procedure test;
var
  MyArray: TCharDynArray;
begin
  Clear(MyArray);
end;
这段代码可以很好地编译。当然,它没有做任何有用的事情(AArray参数没有设置为“var”,因此在为每个项目分配#0之前,它会复制到堆栈上)。但至少,它可以编译

在实践中,我发现更容易为动态数组定义或使用高级类型(如TIntegerDynArray),因为它至少允许您使用var将数组作为引用传递,从而避免在堆栈上进行复制,并使代码更快

关于到PChar的映射,所有动态数组都是这样:您可以将TIntegerDynArray映射到指针,然后将其用作PInteger或PIntegerArray:

procedure AddInteger(var Values: TIntegerDynArray; Value: integer);
var n: integer;
begin
  n := Length(Values);
  SetLength(Values,n+1);
  Values[n] := Value;
end;

procedure Loop(V: PInteger);
begin
  if V<>nil then
    while V^<>0 do begin
      write(V^,' ');
      inc(V); // go to next integer in array
    end;
end;

var IntArray: TIntegerDynArray;
begin
  Loop(pointer(IntArray)); // will display nothing, since pointer(IntArray)=nil for IntArray=[]
  AddInteger(IntArray,2);
  AddInteger(IntArray,3);
  AddInteger(IntArray,0);
  Loop(pointer(IntArray)); // will display '2 3 '  
end.
procedure AddInteger(变量值:TIntegerDynArray;值:整数);
var n:整数;
开始
n:=长度(值);
设置长度(值,n+1);
值[n]:=值;
结束;
程序循环(V:PInteger);
开始
如果是Vnil那么
当V^0开始时
写(V^,”);
公司(V);//转到数组中的下一个整数
结束;
结束;
变量IntArray:TIntegerDynArray;
开始
循环(指针(数组));//将不显示任何内容,因为指针(IntArray)=nil表示IntArray=[]
AddInteger(IntArray,2);
AddInteger(IntArray,3);
加法器(IntArray,0);
循环(指针(数组));//将显示“2 3”
结束。

问题是“字符数组”代码与“整数数组”不一致肯定是在编译器内部语言中,而且PChar可以类型转换为字符串。

什么是“预期”?在第一种情况下,数组没有被清除。但是,+1,因为只有一种情况可以编译(即使我们使用
AnsiChar
),这是很奇怪的,因为整数和
AnsiChar
@Andreas之间几乎没有区别,好吧,你让我明白了。空数组没有要清除的内容。我的测试代码调用了SetLength,但我删除了它,因为它与编译错误没有直接关系。对不起,如果我遗漏了什么,问题是什么?“为什么这个错误没有解决?”@splash所以这是一个编译器错误,而不仅仅是一些未记录的开放数组参数限制?
P
如何从
MyArray
知道?不要用指针作弊!;-)虽然它可以编译,但实际上并不起作用。该过程不知道PChar的上限是多少。@Sertac:我完全同意它是某个地方的一个bug;只是想指出它可能来自哪里。希望巴里或丹尼能给我们一些启示。