2013-02-28 3 views
8
uses 
    SysUtils, Variants; 

var 
    VariantSingle: Variant; 
    VTSingle: TVarType; 
    SingleTest: Single; 
    VariantDouble: Variant; 
    DoubleTest: Double; 
    VTDouble: TVarType; 

begin 
    SingleTest := 1.234; 
    VariantSingle := SingleTest; 
    VTSingle := VarType(VariantSingle) and varTypeMask; 

    DoubleTest := 1.23456; 
    VariantDouble := DoubleTest; 
    VTDouble := VarType(VariantDouble) and varTypeMask; 

    WriteLn(Format('VarType: Single: %d, Double %d', [VTSingle, VTDouble])); 
end. 

Код выше вывод будет:Почему присвоение одного варианта варианту приводит к варианту varDouble?

VarType: Single: 5, Double 5

От System.pas

varSingle = $0004; { vt_r4   4 } 
varDouble = $0005; { vt_r8   5 } 

Таким образом, я бы ожидать VTSingle к be - not 5
Что мне не хватает?

ответ

5

Библиотеки Delphi позволяют реализовать все назначения с плавающей запятой вариантам посредством вызова _VarFromReal. И эта функция выглядит следующим образом:

procedure _VarFromReal(var V: TVarData; const Value: Real); 
begin 
    if (V.VType and varDeepData) <> 0 then 
    VarClearDeep(V); 
    V.VType := varDouble; 
    V.VDouble := Value; 
end; 

Обратите внимание, что это использует тип varDouble. И включает неявное преобразование в Real, которое является псевдонимом для Double. Я не уверен, почему дизайнеры выбрали именно этот маршрут, но следствием этого выбора является поведение, которое вы наблюдаете.

Простой способ сделать varSingle вариант вы можете использовать:

VariantSingle := VarAsType(SingleTest, varSingle); 

Хотя это будет конвертировать SingleTest в Double, а затем снова к Single.

Чтобы избежать этого ненужного преобразования, написать свой собственный помощник:

function VarFromSingle(const Value: Single): Variant; 
begin 
    VarClear(Result); 
    TVarData(Result).VSingle := Value; 
    TVarData(Result).VType := varSingle; 
end; 

который можно назвать так:

VariantSingle := VarFromSingle(SingleTest); 

Этот последний подход является правильным решением, на мой взгляд.

+0

Вы переводили процедуру '_VarFromReal' из asm в Pascal? По крайней мере, в Delphi 2009 он реализован как процедура 'asm'. –

+0

@AndreasRejbrand Современные Delphis также имеют версии Pascal для новых целей без x86. Поэтому я использовал версию Pascal. –

Смежные вопросы