如何获取给定变体的实际类型的内存大小?

时间:2015-09-24 10:33:28

标签: delphi variant

请考虑以下代码:

procedure Test;
var
  IntGenuine: UInt64;
  IntVariant: Variant;

begin
  IntGenuine := 0;
  IntVariant := UInt64(0); // The type of the variant is UInt64 now

  WriteLn('Size of IntGenuine = ', SizeOf(IntGenuine)); // Output: 8
  WriteLn('Size of IntVariant = ', SizeOf(IntVariant)); // Output: 24
end;

我知道声明SizeOf(IntVariant)等同于SizeOf(Variant)。它获取类型Variant的大小,而不是变体的实际类型的大小(在这种情况下为UInt64)。

如何获取给定变体的实际类型的内存大小?

3 个答案:

答案 0 :(得分:3)

你可以创建一个像这样的函数:

SELECT id, date
FROM table
WHERE str_to_date(date, '%m/%d/%Y') BETWEEN '2015-09-10' and '2015-09-23';

这里Program Project1; {$APPTYPE CONSOLE} uses Variants, SysUtils; function GetVarTypeSize(AVarType : TVarType; var isArray : boolean) : integer; begin isArray := AVarType <> (AVarType and VarTypeMask); case AVarType and VarTypeMask of varSmallInt: result := SizeOf(SmallInt); varInteger: result := SizeOf(Integer); varSingle: result := SizeOf(Single); varDouble: result := SizeOf(Double); varCurrency: result := SizeOf(Currency); varDate: result := SizeOf(TDateTime); varOleStr: result := SizeOf(PWideChar); varDispatch: result := SizeOf(Pointer); varError: result := SizeOf(HRESULT); varBoolean: result := SizeOf(WordBool); varUnknown: result := SizeOf(Pointer); varShortInt: result := SizeOf(ShortInt); varByte: result := SizeOf(Byte); varWord: result := SizeOf(Word); varLongWord: result := SizeOf(LongWord); varInt64: result := SizeOf(Int64); varUInt64: result := SizeOf(UInt64); varString: result := SizeOf(Pointer); varAny: result := SizeOf(Pointer); varArray: result := SizeOf(PVarArray); varByRef: result := SizeOf(Pointer); varUString: result := SizeOf(Pointer); varRecord: result := SizeOf(TVarRecord); else result := -1; //unknown end; end; var v : Variant; b : boolean; begin v := 3.141592654; // double Write(GetVarTypeSize(VarType(v), b)); if b then WriteLn(' : Is array') else WriteLn; v := 3; // byte Write(GetVarTypeSize(VarType(v), b)); if b then WriteLn(' : Is array') else WriteLn; v := integer(3); // integer Write(GetVarTypeSize(VarType(v), b)); if b then WriteLn(' : Is array') else WriteLn; v := Now; // DateTime Write(GetVarTypeSize(VarType(v), b)); if b then WriteLn(' : Is array') else WriteLn; v := VarArrayCreate([0,9], varDouble); //array ! careful Write(GetVarTypeSize(VarType(v), b)); if b then WriteLn(' : Is array') else WriteLn; ReadLn; end. 将掩盖定义变量数组的位。如果基本变量是数组类型,则屏蔽它将告诉您数组元素的类型。

您可以阅读更多in the documentation

答案 1 :(得分:2)

如果你的变量是variant,它将在Win32下使用(至少)16个字节,在Win64下使用24个字节,存储任何值

此变量的内存大小始终是variant结构之一,TVarData中定义为System.pas

定义:

var
  IntVariant: Variant;

实际上与定义相同:

var
  IntVariant: TVarData;

使用一些初始化/终结魔术:

var
  IntVariant: TVarData;
begin
  IntVariant.VType := varEmpty;
  try
    ...
  finally
    VarClear(variant(IntVariant));
  end;
end;

如果您不存储任何内容(varEmptyvarNull),它仍会使用16/24字节。如果存储boolean,它仍将使用16/24字节。如果它存储了一些string,则必须将堆分配的存储文本值添加到16/24字节。

答案 2 :(得分:2)

变体存储在幕后类型TVarData的记录中。

System.TVarData Record

PVarData = ^TVarData;
TVarData = packed record
  case Integer of
    0: (VType: TVarType;
        case Integer of
          0: (Reserved1: Word;
              case Integer of
                0: (Reserved2, Reserved3: Word;
                    case Integer of
                      varSmallInt: (VSmallInt: SmallInt);
                      varInteger:  (VInteger: Integer);
                      varSingle:   (VSingle: Single);
                      varDouble:   (VDouble: Double);
                      varCurrency: (VCurrency: Currency);
                      varDate:     (VDate: TDateTime);
                      varOleStr:   (VOleStr: PWideChar);
                      varDispatch: (VDispatch: Pointer);
                      varError:    (VError: HRESULT);
                      varBoolean:  (VBoolean: WordBool);
                      varUnknown:  (VUnknown: Pointer);
                      varShortInt: (VShortInt: ShortInt);
                      varByte:     (VByte: Byte);
                      varWord:     (VWord: Word);
                      varLongWord: (VLongWord: LongWord);
                      varInt64:    (VInt64: Int64);
                      varUInt64:   (VUInt64: UInt64);
                      varString:   (VString: Pointer);
                      varAny:      (VAny: Pointer);
                      varArray:    (VArray: PVarArray);
                      varByRef:    (VPointer: Pointer);
                      varUString:  (VUString: Pointer);
                      varRecord:   (VRecord: TVarRecord);
                      //$ffff:     (VLargest: TLargestVarData);
                   );
                1: (VLongs: array[0..{$IFDEF CPUX64}4{$ELSE}2{$ENDIF}] of LongInt);
             );
          2: (VWords: array [0..{$IFDEF CPUX64}10{$ELSE}6{$ENDIF}] of Word);
          3: (VBytes: array [0..{$IFDEF CPUX64}21{$ELSE}13{$ENDIF}] of Byte);
        );
    1: (RawData: array [0..{$IFDEF CPUX64}5{$ELSE}3{$ENDIF}] of LongInt);
end;

可以获取您要查找的信息,将Variant变量转换为此类型:

var
  varData: TVarData;
  intVariant: Variant;
  size: Integer;
begin
  intVariant := UInt64(10);
  varData := TVarData(IntVariant);

  case varData.VType of
    varUInt64: size := SizeOf(varData.VUInt64);
    varInteger: size := SizeOf(varData.VInteger);
  . . .
  end;
end;

...但以上不是通常的方法:

var
  intVariant: Variant;
  size: Integer;
  vType: Integer;
begin     
  vType := VarType(intVariant) and VarTypeMask;
  case vType of
    varUInt64: size := SizeOf(UInt64);
    varInteger: size := SizeOf(Integer);
    . . .
  end;
end;