Как мне получить вариант из указателя в Delphi?

#delphi #pointers #variant

#delphi #указатели #вариант

Вопрос:

Мне нужно иметь возможность преобразовать простой указатель в вариант. Я знаю, что указатель указывает на вариант, но, похоже, я не могу вернуть его обратно. Прямое приведение (как я и думал) завершается неудачей:

 Result := Variant(FAddress)^
  

возвращает ошибку компилятора: [Ошибка DCC] E2089 Недопустимый набор типов

Я также просмотрел модуль variants.pas, но мне ничего не бросилось в глаза.

Очевидно, я что-то упускаю. Какой способ это сделать?

Ответ №1:

Если указатель указывает на вариант, то его тип — PVariant. Приведите его к этому типу, а затем разыменуйте:

 Result := PVariant(FAddress)^;
  

А еще лучше, для начала объявите FAddress с правильным типом, и тогда вам не нужно вводить тип:

 var
  FAddress: PVariant;

Result := FAddress^;
  

Компилятор считает вашу попытку приведения к типу недопустимой, потому что Variant — это больший тип, чем Pointer. Компилятор не знает, где взять дополнительные данные для создания полного значения Variant. И если приведение типа было допустимым, использование ^ оператора в любом случае не разрешено для вариантов. Возможно, вам это сошло с рук:

 Result := Variant(FAddress^);
  

Мне это никогда не нравилось; если FAddress является нетипизированным указателем, то при его разыменовании получается значение вообще без какого-либо размера или типа, и просто странно вводить такую вещь.

Комментарии:

1. Забавно, у меня нет проблем с Variant(FAddress^) . Я не вижу, чтобы это чем-то отличалось от PVariant(FAddress)^ .

2. Спасибо, Роб, кажется, это работает. На самом деле я модифицирую существующую библиотеку и не хотел (пока) вносить радикальные изменения.

3. @David, в Variant(FAddress^) промежуточное значение в этом выражении вообще не имеет типа. Я рассматриваю это как мгновенное программирование «без сети», и это вызывает у меня дрожь. В PVariant(FAddress)^ где-то все еще есть вещь без типов, но мы никогда не обращаемся к ней напрямую. Сначала мы присваиваем ему тип, а затем начинаем его использовать.

4. @Rob Я знаю, к чему ты клонишь, но подумай об этом так. Поскольку вы не можете разыменовать вещь без типа указателя, как это может означать что-то отличное от вашей предпочтительной версии? Другой способ выразить это так, что промежуточного значения нет. В вашей версии также нет промежуточного значения.

5. @Rob Или таким образом. Для того, чтобы назначить переменную, вам нужно указать местоположение и тип как lvalue, так и rvalue. Вы не можете выполнить присваивание, используя только тип или просто местоположение. Итак, вы должны указать оба, и вы можете сделать это в любом порядке. По крайней мере, это ментальная модель, которая у меня есть!