Разрешена динамический массив CHAR, если тип параметра является открытым массивом CHAR?
-
04-10-2019 - |
Вопрос
Я смотрел на 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.