问题 当参数类型是Char的数组打开时,是否允许动态数组Char?


我在看 Delphi:Char和TCharArray数组“不兼容的类型” 并开始尝试。我发现的是相当有趣的。

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.

这个简单的小例子展示了如何使用Open Array参数将动态数组传递给过程。它完全按预期编译和运行。

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,它仍然在发生。


10491
2017-09-23 19:05


起源

什么是“预期的”?在第一种情况下不清除该数组。 - Andreas Rejbrand
仍然,+1,只有一个案例编译(即使我们使用 AnsiChar),这是相当奇怪的,因为整数和a之间几乎没有差别 AnsiChar。 - Andreas Rejbrand
@Andreas,好的,你让我在那儿。空数组无需清除。我的测试代码调用了SetLength但我删除了它,因为它与编译错误没有直接关系。 - Kenneth Cochran
对不起,如果我错过了什么,但问题是什么? “为什么这个bug没有解决?” - splash
@splash所以这是一个编译器错误而不仅仅是开放数组参数的一些未记录的限制? - Kenneth Cochran


答案:


由于文档特别提到Char类型的开放数组参数与动态数组兼容,这应该是一个bug。从 '打开数组参数'

function Find(A: array of Char):   整数;
[...]
注意: [...]   上一个示例创建一个函数   它接受任何Char元素数组,   包括(但不限于)动态   阵列。 [...]


4
2017-09-24 01:10





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

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.

问题是“数组的char”代码与“整数数组”不一致当然是在编译器内在函数中,并且事实上PChar可以被类型转换为字符串。


4
2018-01-06 08:55





我认为原因是 array of Char 兼容 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


2
2017-09-23 19:38



如何 P 知道 MyArray?不要用指针作弊! ;-) - splash
虽然它编译,但实际上并不起作用。该程序不知道PChar的高限是什么。 - Sertac Akyuz
@Sertac:我完全同意这是某个地方的错误;只是想指出它可能来自哪里。希望巴里或丹尼能在这里说清楚。 - Jeroen Wiert Pluimers