Is a dynamic array of Char allowed when the parameter type is open array of Char?

后端 未结 3 2023
时光说笑
时光说笑 2020-12-31 10:57

I was looking at Delphi: array of Char and TCharArray "Incompatible Types" and started experimenting. What I discovered is rather interesting.

proc         


        
相关标签:
3条回答
  • 2020-12-31 11:44

    Since the documentation specifically mentions open array parameters of type Char to be compatible with dynamic arrays, this should be a bug. From 'Open Array Parameters':

    function Find(A: array of Char): Integer;
    [...]
    Note: [...] The previous example creates a function that takes any array of Char elements, including (but not limited to) dynamic arrays. [...]

    0 讨论(0)
  • 2020-12-31 11:45

    I think the reason is that array of Char is compatible with PChar, as this code does compile:

    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.
    

    That is probably for historic reasons.
    Hopefully Barry Kelly or Danny Thorpe will kick in and provide some more feedback on this.

    --jeroen

    0 讨论(0)
  • 2020-12-31 11:52

    You can work with this kind of array, defining your own type:

    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;
    

    This code will compile fine. It doesn't do anything useful of course (the AArray parameter is not set as "var", so it's copied on the stack before assigning a #0 to every item). But at least, it compiles.

    In practice, I found out more easy to define or use high-level of types for dynamic arrays (like TIntegerDynArray), because at least it allows you to pass the array as reference, using a var, therefore avoiding to make a copy on stack, and make your code faster.

    About the mapping to a PChar, it's usual for all dynamic arrays: you can map a TIntegerDynArray to a pointer, then use it as a PInteger or a 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.
    

    The problem is the "array of char" code beeing inconsistent with "array of integer" is certainly in compiler intrinsics, and the fact that a PChar can be type-casted to a string.

    0 讨论(0)
提交回复
热议问题