【问题标题】:Is a dynamic array of Char allowed when the parameter type is open array of Char?当参数类型是 Char 的开放数组时,是否允许 Char 的动态数组?
【发布时间】:2011-04-16 10:50:32
【问题描述】:

我正在查看Delphi: array of Char and TCharArray "Incompatible Types" 并开始尝试。我发现的很有趣。

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'

为什么会这样?

搜索了一段时间后,我发现了this QC 报告。我正在运行 Delphi 2009,它仍在运行。

【问题讨论】:

  • 什么是“预期”?第一种情况下数组没有被清空。
  • 仍然,+1,只有一种情况可以编译(即使我们使用AnsiChar),这很奇怪,因为整数和AnsiChar 之间几乎没有区别.
  • @Andreas,好的,你把我带到了那里。一个空数组没有什么要清除的。我的测试代码调用了 SetLength,但我删除了它,因为它与编译错误没有直接关系。
  • 抱歉,如果我遗漏了什么,请问有什么问题吗? “为什么这个错误没有解决?”
  • @splash 所以这是一个编译器错误,而不仅仅是开放数组参数的一些未记录的限制?

标签: delphi dynamic-arrays open-array-parameters


【解决方案1】:

由于文档特别提到 Char 类型的开放数组参数与动态数组兼容,这应该是一个错误。来自'Open Array Parameters'

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

【讨论】:

    【解决方案2】:

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

    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 可以强制类型转换为字符串这一事实。

    【讨论】:

      【解决方案3】:

      我认为原因是array of CharPChar 兼容,因为这段代码确实可以编译:

      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.
      

      这可能是出于历史原因。
      希望Barry KellyDanny Thorpe 能够参与进来并就此提供更多反馈。

      --杰罗恩

      【讨论】:

      • P 是如何从MyArray 得知的?不要用指针作弊! ;-)
      • 虽然它编译,但它实际上并不工作。该过程不知道 PChar 的上限是多少。
      • @Sertac:我完全同意这是某个地方的错误;只是想指出它可能来自哪里。希望巴里或丹尼能在这里有所启发。
      猜你喜欢
      • 2014-09-18
      • 2016-04-04
      • 1970-01-01
      • 2013-06-23
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多