【问题标题】:Delphi: array of Char and TCharArray "Incompatible Types"Delphi:Char 和 TCharArray “不兼容类型”的数组
【发布时间】:2011-04-16 08:46:46
【问题描述】:

我在下面的评论中遇到过这个“不兼容的类型”错误几次,但一直不满意为什么 Delphi 2007 不直接支持这个错误:

program Project1; {$APPTYPE CONSOLE}

type TCharArray = array of Char;

procedure DoArray(Chars: array of Char);
begin
end;

function ReturnTCharArray: TCharArray;
var CharArray: TCharArray;
begin
  Result := CharArray;
end;

begin
  DoArray(ReturnTCharArray); // [DCC Error] Project1.dpr(18): E2010 Incompatible types: 'Array' and 'TCharArray'
end.

难道不能将一个数组类型“别名”为另一个相互兼容的数组类型吗?假设我无法更改 DoArray 的声明(它是第三方库的一部分),我如何编写一个函数返回与 DoArray 的参数兼容的字符数组?直截了当的“函数 ReturnAChar:Char 数组;”导致“需要标识符,但找到了 'ARRAY'”错误。我什至尝试使用var“char数组”婴儿车将返回数组的函数更改为程序,但这也不允许在程序中设置“char数组”参数的长度(“无法传递常量对象作为 var 参数”)。

【问题讨论】:

    标签: arrays delphi types char


    【解决方案1】:

    这实际上可能是编译器错误(或从未正确记录的限制)。我做了一些实验,发现你可以将一个动态数组(类型化或非类型化)传递给一个期望几乎所有类型都有一个开放数组的过程......除了 Char 和 WideChar。

    请参阅Is a dynamic array of Char allowed when the parameter type is open array of Char? 了解问题描述和可能的解决方法。

    【讨论】:

    • 出于某种原因,我一直认为动态数组和开放数组是不兼容的......我真的很惊讶只有 char 和 Widechar 是。看起来他们是我早期对 Delphi 数组进行实验的人,我再也没有回去过。或者可能是在 Delphi 5 中?
    • @Ken 文档声称开放数组参数可以处理任何相同类型的数组。所以我很惊讶 Char 数组和 WideChar 数组没有编译。
    • @KennethCochran:它应该接受 any 数组,甚至是 Char/WideChar 数组。
    【解决方案2】:

    typed @ operator 关闭时,编译器不会检查您分配给指针的内容,因此您可以调用带有错误 参数的过程:

    program Project1; {$APPTYPE CONSOLE}
    
    type TCharArray = array of Char;
    
    procedure DoArray(Chars: array of Char);
    begin
    end;
    
    function ReturnTCharArray: TCharArray;
    var CharArray: TCharArray;
    begin
      Result := CharArray;
    end;
    
    type TFakeDoArray = procedure(Chars: TCharArray);
    
    var
      FakeDoArray: TFakeDoArray;
    begin
      FakeDoArray := @DoArray;
      FakeDoArray(ReturnTCharArray);
    end.
    

    虽然编译器不会抱怨,但由于 'Jeroen' 在他对 Mason's answer 的评论中指出的原因,这将不起作用。

    然后您可以尝试声明您的假程序与具有开放数组参数的程序兼容:

    program Project1; {$APPTYPE CONSOLE}
    
    type TCharArray = array of Char;
    
    procedure DoArray(Chars: array of Char);
    begin
    end;
    
    function ReturnTCharArray: TCharArray;
    var CharArray: TCharArray;
    begin
      Result := CharArray;
    end;
    
    type
      TFakeDoArray = procedure(AnArray: Pointer; High: Integer);
    
    var
      FakeDoArray: TFakeDoArray;
      Tmp: TCharArray;
    begin
      FakeDoArray := @DoArray;
      Tmp := ReturnTCharArray;
      FakeDoArray(Tmp, High(Tmp));
    end.
    

    感谢 Rudy 的 great article。以及相关文档(来自Program Control):

    一个开放数组参数被传递为 两个 32 位值。第一个值为 指向数组数据的指针,以及 第二个值比 数组中的元素数。

    【讨论】:

      【解决方案3】:

      你没有。 Pascal 按名称处理数组类型,而不是按描述处理,并且始终如此。为什么不能更改 DoArray 的声明? (为什么一开始是这样写的?)

      【讨论】:

      • +1;正确的! (哦,顺便说一句:还有“开放数组”与“类型数组”的区别,这可能是 Anagoge 下一步要碰到的地方)
      • DoArray 是我不想(实际上不能)编辑的第三方库的一部分。我可以理解您有时希望按名称类型的类型安全,但对我来说,这种语言限制比有用更烦人。有没有办法说服 Delphi 从函数中返回文字/精确的“字符数组”?这似乎是一个相当基本的要求。
      • @Anagoge:不,据我所知没有。我认为这就是他们在 Delphi 2009 中添加 TArray<T> 的原因。TArray<T> 被定义为 array of T,但由于它现在是一个命名类型,它解决了所有这些问题。
      • 这个答案偏离了重点。 DoArray 接受一个开放的数组。
      • @Rudy 这是一个编译器错误。这不应该是最受好评的答案。社区精神要做的事情就是对此投反对票。
      【解决方案4】:

      我还没有看到提到的一点是 TCharArray 是动态数组类型,而在

      procedure DoArray(Chars: array of Char); 
      

      Chars 是一个开放数组参数。没有声明动态数组参数的语法。要拥有动态数组参数,需要将其声明为类型。

      type
        TMyDynArray = array of Integer;
      
      procedure DoArray(Integers : TMyDynArray);
      

      【讨论】:

      • 这是不正确的。任何形式的数组都可以传递给开放数组参数。编译器拒绝这是因为编译器有缺陷。
      • 在这个答案中,我在哪里提到动态数组不能作为开放数组参数传递?我只提到array of char 作为参数不会使参数成为动态数组,而是开放数组。而且由于问题抱怨他不能在 DoArray 函数中使用“SetLength”,这表明他想要的不是开放数组参数。那死灵呢?
      猜你喜欢
      • 2012-09-22
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2018-09-11
      • 2019-12-27
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多