#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. Вы не можете выполнить присваивание, используя только тип или просто местоположение. Итак, вы должны указать оба, и вы можете сделать это в любом порядке. По крайней мере, это ментальная модель, которая у меня есть!