内部数据格式(Delphi)

来自RAD Studio
跳转到:航行,搜索

转到内存管理索引

以下主题描述了Delphi数据类型的内部格式。

整数类型

整数值在Delphi中具有以下内部表示形式。

独立于平台的无符号整数类型

平台相关整数类型的值在任何平台上占用相同的位数。

无符号整数类型的值总是正数,并且不涉及符号位有符号整数类型也是如此。无符号整数类型的所有位都占用值的大小,没有其他意义。

字节,UInt8

字节用户界面8是1字节(8位)无符号正整数。这个震级占用所有8位。

整数无符号8位

Word和UInt16

单词用户界面16是2字节(16位)无符号整数。

16位无符号整数

固定UInt、基数和UInt32

固定UInt,红衣主教、和UInt32型是4字节(32位)无符号整数。

32位无符号整数

用户界面64

用户界面64是8字节(64位)的无符号整数。

无符号64位整数

独立于平台的有符号整数类型

带符号整数类型的值用一个前导字符表示数字的符号符号位,用最高有效位表示。符号位为0表示正数,1表示负数。正有符号整数中的其他位被幅度占用。在负符号整数中,其他位由二的补码数值大小的表示(绝对值)。

要获得二者的量级补码:

  1. 从右边开始,找到第一个“1”。
  2. 反转该位左侧的所有位。

例如:

示例1 示例2
震级 0101010 1010101

2的补语

1010110 0101011

短整数,整数8

短整型国际8是1字节(8位)有符号整数。这个符号位'占据最高有效的第7位震级二的补码占用其他7位。

整数有符号正8位
整数有符号负8位

SmallInt和Int16

小型Int国际16是2字节(16位)有符号整数。

16位带符号正整数
整数有符号负16位

固定Int、整数和Int32

固定Int,整数、和国际32是4字节(32位)有符号整数。

32位带符号正整数
带符号整数负32位

国际64

国际64是8字节(64位)有符号整数。

整数有符号正64位
带符号整数负64位

平台相关整数类型

转换与平台相关的整数类型以适应当前目标平台的位大小。在64位平台上,它们占用64位,在32位平台上它们占用32位(除了LongInt公司长单词类型)。当目标平台的大小与CPU平台相同时,一个依赖于平台的整数正好与CPU寄存器的大小匹配。当特定CPU类型和操作系统需要最佳性能时,通常使用这些类型。

无符号整数NativeUInt

NativeUInt公司是平台相关的无符号整数类型。的大小和内部表示NativeUInt公司取决于当前平台。在32位平台上,NativeUInt公司相当于红衣主教类型。在64位平台上,NativeUInt公司相当于用户界面64类型。

有符号整数NativeInt

NativeInt公司是平台相关的有符号整数类型。的大小和内部表示NativeInt公司取决于当前平台。在32位平台上,NativeInt公司相当于整数类型。在64位平台上,NativeInt公司相当于国际64类型。

LongInt和LongWord

LongInt公司定义有符号整数类型和长单词定义无符号整数类型。LongInt公司长单词除保持不变的64位Windows(32位)外,每个平台上依赖于平台的整数类型大小都会更改。

大小
32位平台和64位Windows平台 64位平台(Windows除外)
LongInt公司 32位(4字节) 64位(8字节)

长单词

32位(4字节) 64位(8字节)
注:RAD Studio中的32位平台包括32位Windows和32位Android。

打开64位平台(Windows除外),如果要使用:

整数子范围类型

使用整数常量定义子范围类型,您定义了整数子范围类型。整数子范围类型表示整数类型(称为基本类型). 基类型是包含指定范围(同时包含最小和最大边界)的最小整数类型。

整数子范围类型变量的内部数据格式取决于其最小和最大边界:

  • 如果两个边界都在-128..127范围内(短Int),变量存储为有符号字节。
  • 如果两个边界都在0..255范围内(字节),变量存储为无符号字节。
  • 如果两个边界都在-32768..32767范围内(小型Int),变量存储为带符号的单词。
  • 如果两个边界都在0..65535范围内(单词),变量存储为无符号单词。
  • 如果两个边界都在-2147483648范围内。2147483647(固定IntLongInt公司在32位平台和64位Windows平台上),变量存储为有符号双字。
  • 如果两个界限都在0..4294967295范围内(固定UInt长单词在32位平台和64位Windows平台上),变量存储为无符号双字。
  • 如果两个边界都在-2^63..2^63-1范围内(国际64LongInt公司在64位iOS平台上),变量存储为有符号四字。
  • 如果两个边界都在0..2^64-1范围内(用户界面64长单词在64位iOS平台上),变量存储为无符号四字。
注:“单词”占用两个字节。

字符类型

在32位和64位平台上:

  • 字符宽字元存储为无符号单词变量,通常使用UTF-16或Unicode编码。

布尔类型

一个布尔值类型存储为字节,一个字节Bool存储为字节,一个WordBool语言类型存储为单词、和LongBool公司存储为朗格特

一个布尔值可以假定值为0(False(错误))和1(真的).字节Bool,WordBool语言、和LongBool公司类型可以假定值为0(False(错误))或非零(真的).

枚举的类型

如果枚举的值不超过256个,并且枚举类型是在{$Z1}状态(默认值)。如果枚举类型有256个以上的值,或者如果该类型是在{$Z2}状态时,它存储为无符号单词。如果枚举类型在{$Z4}状态时,它存储为无符号双字。

真实类型

实数类型存储符号的二进制表示(+-)、指数和有效数。实值具有以下形式

+/-有效数* 2^指数

其中有效数二进制小数点左边有一个位(即,0 <=有效数< 2).

在接下来的图像中,最高有效位始终位于左侧,最低有效位位于右侧。顶部的数字表示每个字段的宽度(以位为单位),最左边的项存储在最高地址。例如,对于真实48值,e(电子)存储在第一个字节中,(f)以下五个字节,以及最后一个字节的最高有效位。

Real48型

在32位和64位平台上,6字节(48位)真实48数字分为三个字段。

1

          39                              

    8    

          (f)

    e(电子)


如果0 <e(电子)<=255,值v(v)数值的计算公式为:

v(v)= (-1)* 2(e-129)*(1.f)

如果e=0,那么v=0

这个真实48类型无法存储非规格化、NaN和无穷大(Inf)。当存储在真实48,而如果尝试将NaNs和infinities存储在真实48

单一类型

在32位和64位平台上,4字节(32位)单个数字分为三个字段。

1

    8    

          23          

    e(电子)

          (f)


价值观v(v)数值的计算公式为:

  • 如果0<e<255,那么v=(-1)* 2(e-127)*(1.f)
  • 如果e=0f<>0,那么v=(-1)* 2(-126)*(0.f)
  • 如果e=0f=0,那么v=(-1)* 0
  • 如果e=255f=0,那么v=(-1)*Inf公司
  • 如果e=255f<>0,那么v(v)是NaN

IEEE要求所有涉及NaN的比较操作都返回false。IEEE 754为所有涉及NaN的关系表达式赋值。

在语法中C类,谓词x!=是正确的,但所有其他:

  • x<y
  • x≤y
  • x==y
  • x>=y(x>=y)
  • x>y

在任何时候都为Falsex个或者两者都是NaN。

Double类型

这个真实类型在当前实现中等价于双重

在32位和64位平台上,8字节(64位)双重数字分为三个字段。

1

     11     

                         52                         

     e(电子)

                         (f)


价值观v(v)数值的计算公式为:

  • 如果0<e<2047,那么v=(-1)* 2(e-1023)*(1.f)
  • 如果e=0f<>0,那么v=(-1)* 2(-1022)*(0.f)
  • 如果e=0f=0,那么v=(-1)*0个
  • 如果e=2047f=0,那么v=(-1)*Inf公司
  • 如果e=2047f<>0,那么v(v)是NaN

IEEE要求所有涉及NaN的比较操作都返回false。IEEE 754为所有涉及NaN的关系表达式赋值。

在语法中C类,谓词x!=是正确的,但所有其他:

  • x<y
  • x小于等于y
  • x==y
  • x>=y
  • x>y

在任何时候都为Falsex个或者两者都是NaN。

扩展类型

扩展与其他实际类型相比,在32位Intel平台上提供了更高的精度,但可移植性较差。小心使用扩展如果您正在创建跨平台共享的数据文件。请注意:

在32位Windows Intel平台上扩展数字表示为10个字节(80位)。扩展数字分为四个字段。

1

        15        

1

                                63                                

        e(电子)

                                (f)

价值观v(v)的值由以下公式给出:

  • 如果0<=e<32767,那么v=(-1)* 2(e-16383)*(i.f)
  • 如果e=32767f=0,那么v=(-1)*Inf公司
  • 如果e=32767f<>0,那么v(v)是NaN

在Windows以外的64位Intel平台(64位Linux或64位macOS Intel)上扩展类型是16个字节,即使数据位仅使用10个字节。

然而,在64位Windows Intel平台和ARM平台(64位macOS ARM、31位Android、64位Android和64位iOS)上扩展类型是的别名双重,只有8个字节。这种差异会对浮点运算中的数字精度产生负面影响。有关更多信息,请参阅多设备应用的Delphi注意事项

Comp类型

8字节(64位)Comp公司数字存储为带符号的64位整数。

货币类型

8字节(64位)货币数字存储为一个64位带符号的带刻度整数,其中4个最低有效数字隐式表示4个小数位。

指针类型

在32位平台上指针类型以4个字节的形式存储为32位地址。

打开64位平台,一个指针类型以8个字节的形式存储为64位地址。

指针值被存储为零。

短字符串类型

一个短字符串字符串占用的字节数等于其最大长度加一。第一个字节包含字符串的当前动态长度,接下来的字节包含字符串中的字符。

长度字节和字符被视为无符号值。最大字符串长度为255个字符加上一个长度字节(字符串[255]).

长字符串类型

类型为的字符串变量Unicode字符串AnsiString公司在32位平台上占用4个字节的内存(在64位平台上占用8个字节),其中包含指向动态分配字符串的指针。当字符串变量为空(包含零长度字符串)时,字符串指针为并且没有与字符串变量关联的动态内存。对于非空字符串值,字符串指针指向动态分配的内存块,该内存块除了包含描述字符串的信息外,还包含字符串值。下表显示了长字符串内存块的布局。

的格式Unicode字符串数据类型(32位和64位)

字段 代码页 单元尺寸 引用计数 长度 字符串数据

(元素大小)

Null术语

抵消

-12

-10

-8

-4

0..(长度-1)

长度*元素大小

目录

字符串数据的16位代码页

字符串数据的16位元素大小

32位参考计数

长度(字符)

ElementSized数据的字符串

NULL字符

中的数字抵消行显示字段的偏移量,描述字符串内容,从指向字符串数据字段(偏移=0),包含包含实际字符串值的内存块。

字符串内存块末尾的NULL字符由编译器和内置字符串处理例程自动维护。这使得可以将字符串直接类型转换为以null结尾的字符串。

另请参阅“新字符串类型:UnicodeString."

对于字符串文字,编译器生成一个内存块,其布局与动态分配的字符串相同,但引用计数为-1。字符串常量的处理方式相同,与文字的唯一区别是它们是指向-1引用计数器块的指针。

当指向字符串结构的指针(来源)分配给字符串变量(目的地),参考计数器指示如何完成此操作。通常,目标的引用计数减少,而源的引用计数增加,因为指针、源和目标在赋值后都指向同一内存块。

如果源引用计数为-1(字符串常量),则创建引用计数为1的新结构。如果目的地不是,参考计数器减少。如果它达到0,则从内存中释放该结构。如果目的地是,不会对其执行其他操作。然后目标将指向新结构。

变量
 目的地 : 字符串;
 来源 : 字符串;
...
目的地 := “qwerty”;  //“destination”变量指向的新创建的内存块(包含“qwerty”字符串)的引用计数现在为1
...
来源 := “asdfgh”; //“destination”变量指向的新创建的内存块(包含“asdfgh”字符串)的引用计数现在为1
目的地 := 来源; //包含“asdfgh”字符串的内存块的引用计数现在为2,并且由于包含“qwerty”字符串的存储块的引用数现在为0,因此内存块被释放。

如果源引用计数不是-1,那么它将递增,目标将指向它。

变量
  目的地, 目的地2, 目的地3: 字符串;
  目的地 := '示例字符串'; //包含“示例字符串”的新创建内存块的引用计数为1。
  目的地2 := 目的地; //包含“示例字符串”的内存块的引用计数现在为2。
  目的地3 := 目的地; //包含“示例字符串”的内存块的引用计数现在为3。
注:没有字符串变量可以指向引用计数为0的结构。结构在达到0引用计数时总是被释放,并且在具有-1引用计数时无法修改。

宽字符串类型

在32位平台上,宽字符串变量占用4个字节的内存(64位上为8个字节),其中包含指向动态分配字符串的指针。当宽字符串变量为空(包含零长度字符串)时,字符串指针为并且没有动态存储器与字符串变量相关联。对于非空字符串值,字符串指针指向动态分配的内存块,该内存块除了包含32位长度指示符外,还包含字符串值。下表显示了Windows上宽字符串内存块的布局。

宽字符串动态内存布局(32位和64位)

抵消

-4

0..(长度-1)

长度

目录

32位长度指示器
(以字节为单位)

字符串

NULL字符

字符串长度是字节数,因此它是字符串中包含的宽字符数的两倍。

宽字符串内存块末尾的NULL字符由编译器和内置字符串处理例程自动维护。这使得可以将宽字符串直接类型转换为以null结尾的字符串。

设置类型

集合是一个位数组,其中每个位都指示元素是否在集合中。一个集合中的最大元素数是256,因此一个集合永远不会占用超过32个字节。特定集合占用的字节数等于

(马克斯第8部分)-(分钟分区8)+1

哪里马克斯分钟是集合的基类型的上下界。特定元素的字节数E类

(E类第8部分)-(分钟第8部分)

该字节中的位号为

E类模块8

哪里E类表示元素的序数值。如果可能,编译器会将集合存储在CPU寄存器中,但如果集合大于依赖于平台的整数类型,或者如果程序包含获取集合地址的代码,则集合始终驻留在内存中。

静态数组类型

静态数组变量占用的内存由以下计算定义长度(数组)*SizeOf(数组[低(数组)])以字节为单位。static-array变量完全作为父数据结构的一部分进行分配。静态数组存储为数组组件类型的元素的连续序列。索引最低的组件存储在最低的内存地址。存储多维数组时,最右边的维度首先递增。

动态数组类型

在32位平台上,动态数组变量占用4个字节的内存(64位上为8个字节),其中包含指向动态分配数组的指针。当变量为空(未初始化)或包含零长度数组时,指针为并且没有与变量关联的动态内存。对于非空数组,变量指向一个动态分配的内存块,该内存块除了包含32位(Win64上为64位)长度指示符和32位引用计数外,还包含该数组。下表显示了动态数组内存块的布局。

动态阵列内存布局(32位和64位)

偏移32位

-8

-4

0..(长度*Size_of_element-1)

偏移64位

-12

-8

0..(长度*Size_of_element-1)

目录

32位参考计数

64位平台上的32位或64位
长度指示器
(元件数量)

数组元素

记录类型

在中声明记录类型时{$A+}状态(默认值),以及声明不包含拥挤的修饰符,该类型是一个未封装的记录类型,并且记录的字段是对齐的,以便CPU根据平台进行有效访问。对齐由每个字段的类型控制。每个数据类型都有一个固有的对齐方式,由编译器自动计算。对齐可以是1、2、4或8,表示必须在其上存储类型值才能提供最有效的访问的字节边界。下表列出了所有数据类型的对齐方式。

类型对齐掩码(仅32位)

类型 对齐

有序类型

类型的大小(1、2、4或8)

真实类型

2用于真实48,4用于单个,8用于双重扩展

短字符串类型

1

数组类型

与数组的元素类型相同

记录类型

记录中字段的最大对齐方式

设置类型

如果为1、2或4,则为类型的大小,否则为1

所有其他类型

由$A指令决定


为了确保未打包记录类型中的字段正确对齐,编译器在对齐为2的字段之前插入一个未使用的字节,如果需要,在对齐为4的字段之前最多插入3个未使用字节。最后,编译器将记录的总大小向上舍入到任何字段的最大对齐指定的字节边界。

具有公共类型规范的字段的隐式封装

Delphi编译器的早期版本(如Delphi 7和更早版本)隐式应用拥挤的对齐到一起声明的字段,即具有公共类型规范的字段。如果指定指令{$OLDTYPELAYOUT ON},则较新的编译器可以重现该行为。此指令字节对齐(打包)具有通用类型规范的字段,即使声明不包括拥挤的修饰符和记录类型未在{$A-}状态。

因此,例如,给出以下声明:

 {$OLDTYPELAYOUT开}
 类型
   TMy记录 = 记录
     一个, B类: 扩展;
     C类: 扩展;
   结束;
 {$OLDTYPELAYOUT关闭}

一个B类由于指定了{$OLDTYPELAYOUT on}指令,并且因为一个B类共享相同的型号规格。然而,对于单独声明的C类字段,编译器使用默认行为并用未使用的字节填充结构,以确保字段出现在四字边界上。

在中声明记录类型时{$A-}声明中包含拥挤的修饰符,则记录的字段不对齐,而是被指定为连续偏移量。这样一个压缩记录的总大小就是所有字段的大小。因为数据对齐可以更改,所以最好将要写入磁盘或传入内存的任何记录结构打包到使用不同版本编译器编译的另一个模块中。

文件类型

文件类型表示为记录。在32位平台上,类型化文件和非类型化文件占用592字节,在64位平台上占用616字节,其布局如下:

 类型
   TFileRec(文件回收) = 拥挤的 记录
     把手: NativeInt公司;
     模式: 单词;
     旗帜: 单词;
     案例 字节 属于
       0: (RecSize(重新调整大小): 红衣主教);
       1: (BufSize(大小): 红衣主教;
    	   BufPos公司: 红衣主教;
    	   BufEnd公司: 红衣主教;
    	   BufPtr公司: _PAnsiChr公司;
    	   OpenFunc(开放式功能): 指针;
    	   InOutFunc(输入输出函数): 指针;
    	   FlushFunc软件: 指针;
    	   关闭Func: 指针;
    	   用户数据: 阵列[1..32] 属于 字节;
    	   姓名: 阵列[0..259] 属于 宽字元; );
  结束;

文本文件在Win 32上占730字节,在Win64上占754字节,其布局如下:

 类型
   TTextBuf(文本Buf) = 阵列[0..127] 属于 字符;
   TTextRec(文本接收) = 拥挤的 记录
     把手: NativeInt公司;
     模式: 单词;
     旗帜: 单词;
     BufSize(大小): 红衣主教;
     BufPos公司: 红衣主教;
     BufEnd软件: 红衣主教;
     BufPtr公司: _PAnsiChr公司;
     OpenFunc(开放式功能): 指针;
     InOutFunc(输入输出函数): 指针;
     FlushFunc软件: 指针;
     关闭Func: 指针;
     用户数据: 阵列[1..32] 属于 字节;
     姓名: 阵列[0..259] 属于 宽字元;
     缓冲器: TTextBuf(文本Buf); //
     代码页: 单词;
     MBCS长度: 短Int;
     MBCSBufPos公司: 字节;
     案例 整数 属于
       0: (MBCS缓冲区: 阵列[0..5] 属于 _AnsiChr公司);
       1: (UTF16缓冲区: 阵列[0..2] 属于 宽字元);
   结束;

把手包含文件的句柄(当文件打开时)。

这个模式字段可以采用以下值之一:

 常数
   fm已关闭 = 70万加元;
   fm输入= D7B1美元;
   fm输出 = D7B2美元;
   fm输入输出= D7B3美元;

哪里fm已关闭表示文件已关闭,fm输入fm输出指示已重置的文本文件(fm输入)或改写(fmOutput(格式输出)),fm输入输出指示已重置或重写的类型化或非类型化文件。任何其他值都表示文件变量未赋值(因此未初始化)。

这个用户数据字段可供用户编写的例程在其中存储数据。

姓名包含文件名,这是一个以空字符(#0)结尾的字符序列。

对于类型化文件和非类型化文件,RecSize(重新调整大小)包含以字节为单位的记录长度私人字段未使用但已保留。

对于文本文件,BufPtr公司是指向缓冲区的指针BufSize(大小)字节,BufPos公司是缓冲区中要读取或写入的下一个字符的索引,并且BufEnd软件是缓冲区中有效字符的计数。OpenFunc(开放式功能),输入输出功能,FlushFunc软件、和关闭Func是指向控制文件的I/O例程的指针;请参阅设备功能。旗帜确定换行符样式,如下所示。

位0清除

左前换行符

位0设置

CRLF换行符

所有其他旗帜位保留供将来使用。

注:对于使用Unicode字符串类型(默认的Delphi字符串类型)课程单位(文件流,TS流读取器,TStream编写器,等等)更有用,因为旧的文件类型的Unicode功能有限,尤其是旧的文本文件类型。

程序类型

在32位平台上,过程指针存储为指向过程或函数入口点的32位指针。方法指针存储为指向方法入口点的32位指针,后跟指向对象的32位指示器。

在64位平台上,过程指针存储为指向过程或函数入口点的64位指针。方法指针存储为指向方法入口点的64位指针,后跟指向对象的64位指示器。

类类型

在32位平台(Win32和Android)上,类类型值存储为指向类实例的32位指针(在64位平台上存储为64位指针),这称为对象。对象的内部数据格式类似于记录的格式。对象的字段按声明顺序存储为连续变量序列。字段始终对齐,对应于未打包的记录类型。因此,对齐对应于中字段的最大对齐对象。从祖先类继承的所有字段都存储在子类中定义的新字段之前。

在32位平台上,每个对象的第一个4字节字段(64位平台上的第一个8字节字段)是指向虚拟方法表(VMT)。每个类只有一个VMT(不是每个对象一个);不同的类类型,无论多么相似,都不会共享VMT。VMT是由编译器自动构建的,永远不会被程序直接操作。指向VMT的指针由构造函数方法自动存储在它们创建的对象中,也永远不会由程序直接操作。

VMT的布局如下表所示。在32位平台上,在正偏移处,VMT由32位方法指针列表(64位平台上的64位方法指针)组成——类类型中每个用户定义的虚拟方法一个指针——按声明顺序排列。每个插槽包含虚拟方法相应入口点的地址。此布局与C++v表和COM兼容。在负偏移量下,VMT包含许多Delphi实现内部的字段。应用程序应该使用TObject中定义的方法来查询这些信息,因为在Delphi语言的未来实现中,布局可能会发生变化。

虚拟方法表布局

抵消
Win32,macOS
抵消
Win64(Win64)
抵消
iOS/ARM、Android/ARM
类型 说明 System.pas中的常量

-88

-200

-108

指针

指向虚拟方法表(或)

vmt自助

-84

-192

-104

指针

指向接口表(或)

vmtIntf表格

-80

-184个

-100

指针

指向自动化信息表(或)

vmt自动表格

-76

-176

-96

指针

指向实例初始化表(或)

vmt单位表

-72

-168

-92

指针

指向类型信息表(或)

vmtType信息

-68

-160

-88

指针

指向字段定义表(或)

vmt字段表

-64

-152

-84

指针

指向方法定义表(或)

vmt方法表

-60

-144

-80

指针

指向动态方法表(或)

vmt动态表

-56

-136

-76

指针

指向包含类名的短字符串的指针

vmt类别名称

-52

-128

-72

红衣主教

实例大小(字节)

vmt实例大小

-48个

-120

-68

指针

指向指向祖先类(或)

vmt父

不适用

不适用

-64

指针

__ObjAddRef方法的入口点

vmtObj添加参考

不适用

不适用

-60

指针

__ObjRelease方法的入口点

vmtObj发布

-44

-112

-56

指针

Equals方法的入口点

vmt等于

-40

-104个

-52

指针

GetHashCode方法的入口点

vmt获取哈希代码

-36

-96

-48个

指针

ToString方法的入口点

vmtToString

-32

-88

-44

指针

指向的入口点的指针安全调用异常方法(或)

vmtSafeCallException异常

-28

-80

-40

指针

的入口点施工后方法

vmt施工后

-24

-72

-36

指针

的入口点销毁前方法

vmt销毁前

-20

-64

-32

指针

的入口点派遣方法

vmt调度

-16

-56

-28

指针

的入口点处理方法方法

vmt默认处理程序

-12

-48个

-24

指针

的入口点新建实例方法

vmt新实例

-8

-40

-20

指针

的入口点FreeInstance(自由实例)方法

vmt自由实例

-4

-32

-16

指针

的入口点销毁析构函数

vmt销毁

0

0

0

指针

第一个用户定义的虚拟方法的入口点

4

8

4

指针

第二个用户定义虚拟方法的入口点

类引用类型

在32位平台(Win32和Android)上,类引用值存储为指向类的虚拟方法表(VMT)的32位指针。

在64位平台(Win64、64位Linux、64位iOS和64位Android)上,类引用值存储为指向类的虚拟方法表(VMT)的64位指针。

变量类型

变体依赖于将数据装箱和拆箱到对象包装器中,以及Delphi帮助类来实现与变体相关的RTL函数。

在32位平台上,变量存储为16字节记录,其中包含类型代码和代码给定类型的值(或对值的引用)。在64位平台上,变量存储为24字节记录。这个系统系统。变体单位定义变量的常量和类型。

这个TVarData公司类型表示的内部结构变体变量(在Windows上,这与变体COM和Win32 API使用的类型)。这个TVarData公司type可用于Variant变量的类型转换,以访问变量的内部结构。这个TVarData公司记录包含以下字段:

  • 这个V类型的字段TVar类型类型具有单词(16位)大小。V类型在低12位中包含变量的类型代码(由varType掩码 =$FFF常数)。此外varArray(变量阵列) = $2000可以设置位以指示变量是数组,并且变量ByRef(= $4000)位可以设置为指示变量包含相对于值的引用。
  • 这个保留1,保留2、和保留3(单词大小)字段未使用。

The contents of the remaining 8 bytes (32-bit platform) or 16 bytes (64-bit platform) of aTVarData公司记录取决于V类型字段如下:

这个varString变量字符串类型代码是私有的。包含varString变量字符串值永远不应该传递给非Delphi函数。在Windows平台上,Delphi的自动化支持自动转换varString变量字符串变量到varOleStr公司变量,然后将其作为参数传递给外部函数。

另请参见