2013-02-28 50 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變體會導致varDouble變體?

VARTYPE:單:5,雙5

從System.pas

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

因此,我期望VTSingle到是 - 不是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'程序來實現的。 – 2013-02-28 11:11:15

+0

@AndreasRejbrand現代Delphis還擁有Pascal版本,以利於新的非x86目標。所以我在這裏使用了Pascal版本。 – 2013-02-28 11:13:36

相關問題