Delphi: массив Char и TCharArray "Несовместимые типы" - PullRequest
3 голосов
/ 23 сентября 2010

Я несколько раз сталкивался с этой ошибкой «Несовместимые типы» в комментарии ниже и никогда не был доволен, почему это не поддерживается напрямую в 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 (оно является частью сторонней библиотеки), как мне написать функцию, возвращающую массив char, совместимый с параметром DoArray? Простая "функция ReturnAChar: массив Char;" приводит к ошибке «Идентификатор ожидается, но« ARRAY »найден». Я даже пытался изменить функцию, возвращающую массив, в процедуру с коляской var «array of Char», но это также не позволяет установить длину параметра «array of Char» в процедуре («Невозможно передать объект Constant в качестве параметра var ").

Ответы [ 4 ]

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

Это может быть ошибка компилятора (или ограничение, которое никогда не было задокументировано должным образом). Я провел некоторые эксперименты и обнаружил, что вы можете передать динамический массив (типизированный или нет) процедуре, ожидающей открытый массив почти для каждого типа ... кроме Char и WideChar.

См. Разрешен ли динамический массив Char, когда тип параметра - открытый массив Char? для описания проблемы и возможного обходного пути.

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

Когда 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' указывает в своем комментарии на ответ Мейсона , это не будет работать.

Затем вы можете попытаться объявить вашу поддельную процедуру совместимой с процедурой с параметром открытого массива:

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.

Кредиты причитаются Руди за его замечательную статью . И соответствующая документация (от Управление программой ):

Параметр открытого массива передается как два 32-битных значения. Первое значение указатель на данные массива и второе значение на единицу меньше количество элементов в массиве.

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

Ты не.Паскаль обрабатывает типы массивов по имени, а не по описанию, и всегда имеет.Почему вы не можете изменить объявление DoArray?(И почему это было написано именно так?)

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

Одна вещь, о которой я еще не упомянул, это то, что TCharArray - это динамический тип массива, тогда как в

procedure DoArray(Chars: array of Char); 

Chars - параметр открытого массиваНет синтаксиса для объявления параметра динамического массива.Чтобы иметь параметр динамического массива, он должен быть объявлен как тип.

type
  TMyDynArray = array of Integer;

procedure DoArray(Integers : TMyDynArray);
...