Разрешается ли динамический массив Char, если тип параметра - открытый массив Char? - PullRequest
11 голосов
/ 23 сентября 2010

Я смотрел на 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'

С чего бы это?

После поиска я обнаружил этот отчет о контроле качества. Я использую Delphi 2009, и он все еще происходит.

Ответы [ 3 ]

4 голосов
/ 24 сентября 2010

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

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

4 голосов
/ 06 января 2011

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

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.

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

2 голосов
/ 23 сентября 2010

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

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

- Йерун

...