Разрешена динамический массив CHAR, если тип параметра является открытым массивом CHAR?

StackOverflow https://stackoverflow.com/questions/3781691

Вопрос

Я смотрел на Delphi: Array of 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.

Этот простой небольшой пример показывает, как вы можете передавать динамический массив к процедуре с использованием параметра открытого массива. Он компилирует и работает точно так, как и ожидалось.

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 и все еще происходящее.

Это было полезно?

Решение

Поскольку документация специально упоминает открытые параметры массива типового символа, совместимы с динамическими массивами, это должно быть ошибкой. От «Открытые параметры массива»:

function Find(A: array of Char):Целое число;
[...]
Примечание: ...] Предыдущий пример создает функцию, которая принимает любой массив элементов CHAR, в том числе (но не ограничиваясь) динамическими массивами. [...

Другие советы

Вы можете работать с таком родом массива, определяя свой собственный тип:

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;

Этот код будет компилировать штраф. Это не делает ничего полезного, конечно (параметр Aarlay не устанавливается как «var», поэтому он скопирован на стеке перед назначением # 0 на каждый элемент). Но, по крайней мере, он компилируется.

На практике я узнал более простым в определении или использовании высокоуровневых типов для динамических массивов (например, Tintegerdynarray), потому что, по крайней мере, он позволяет вам пройти массив в качестве ссылки, используя VAR, поэтому избегая, чтобы сделать копию на стеке И сделайте свой код быстрее.

О картировании до PCHAR, это обычно для всех динамических массивов: вы можете сопоставить Tintegerdynarray к указателю, а затем использовать его как пинтегер или Pintegerray:

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.

Проблема в том, что «массив CAR» кода, несовместимый с «массивом целочисленного», безусловно, в недрах компилятора, и тот факт, что PCHR может быть выбран в строке.

Я думаю, что причина в том, что 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.

Это, вероятно, для исторических причин.
С надеждой Барри Келли или Дэнни Торп Буду пинать и предоставить еще несколько отзывов об этом.

- jereen.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top