`
美丽的小岛
  • 浏览: 298139 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

DELPHI中记录的存储方式[转]

 
阅读更多

在DELPHI中,我们用record关键字来表明一个记录,有时候,我们还会看到用packed record来声明的记录,这二者的区别就在于存储方式的不同;在windows中,内存的分配一次是4个字节的,而Packed按字节进行内存的申请和分配,这样速度要慢一些,因为需要额外的时间来进行指针的定位。因此如果不用Packed的话,Delphi将按一次4个字节的方式申请内存,因此如果一个变量没有4个字节宽的话也要占4个字节!这样浪费了一些空间,但提高了效率。

例如一个记录,以,sizeof(okwary)应该得到8。而如果使用packed关键字,那么sizeof(okwary)则得到5。

   type okwary= record
     age : integer;
     sex : shortint;    
   end;

      其中age是integer类型,正好4个字节,而sex是showint类型,占用一个字节,但基于4字节得内存分配方式,这里它也将占用4个字节。


DELPHI中的变体记录

在DELPHI中,观察Tmessage和TTypeData的定义,从关键字record,你一眼就可以看出,它是一个记录类型,但仔细观察,你又会发现在它的定义中出现了case关键字。它代表什么呢?

它代表此记录是变体记录。让我们先去了解一下变体记录。

一个典型的变体记录定义如下:

type  recordTypeName  =  record  
   fieldList1:  type1;  
   ...  
   fieldListn:  typen;  
case  tag:  ordinalType  of  
   constantList1:  (variant1);  
   ...  
   constantListn:  (variantn);  
end

其中case到结尾部分定义了多个变体字段。所有变体字段共享一段内存大小又最大变体字段决定。

使用变体记录时要注意: 

(1)Long  String、WideString、Dynamic  Array、Interface的大小都是指针大小,  OleVariant其实就是COM  SDK中的VARIANT结构,大小是16字节。

但在Object  Pascal中它们都需要自动终结化,如果它们出现在variant  part中,编译器就无法知道它们是否应该进行终结化――因为不知道当前存储的是哪种类型。   

(2)所有变体字段共享一段内存。而共享内存的大小则由最大变体字段决定。 

(3)当tag存在时,它也是记录的一个字段。也可以没有tag。 

(4)记录的变体部分的条件域必须是有序类型

(5)记录类型中可以含有变体部分,有点象case语句,但没有最后的end,变体部分必需在记录中其他字段的声明之后

 

事实上Delphi中内存的几乎所有的变体记录都有一个特点(尽管这不是要求的),就是所有变体部份长度部和都是一样的,比如:

   TMessage = packed record
     Msg: Cardinal;
     case Integer of
       0: (
         WParam: Longint;
         LParam: Longint;
         Result: Longint);
       1: (
         WParamLo: Word;
         WParamHi: Word;
         LParamLo: Word;
         LParamHi: Word;
         ResultLo: Word;
         ResultHi: Word);
   end;

WParam,LParam,Result三个字段的长度和是12个字节,而WParamLo,WParamHi,LParamLo,LParamHi,ResultLo,ResultHi六个字段之和也是12个字符,同时仔细观察,会发现后面六个字段中的每两个字段与前面三个字段中的每一个字段都是对应的.

再看看
   TRect = packed record
     case Integer of
       0: (Left, Top, Right, Bottom: Longint);
       1: (TopLeft, BottomRight: TPoint);
   end;
是不是也是一样的呢?

 

变体记录得作用

(1)节约空间。对于那些要根据条件而决定是否存储得类型,完全可以利用变体记录来达到节约空间得效果。例如,一个公司的员工薪水可以是月薪、年薪等方式,那么并没有必要在记录中都分配空间而又用不到。

(2)类型的转换。例如,如果有一个64位的整数类型作为变体的第一个字段,一个32位的整数Integer类型作为另一个变体的第一个字段,那么可以向64字段赋值然后以整数Integer字段读出其前32位

 

 

//假如有这样一个员工登记表
type TpersonRec = record
    ID: Integer;            {员工编号}
    case Boolean of         {根据分类}
      True:  (A: Cardinal); {如果是股东, 登记年薪}
      False: (B: Word);     {如果不是,   登记日薪}
  end;
var
  personRec: TpersonRec;
begin
  {先算一算这个结构的大小:
    ID 是 Integer  类型, 应该是   4  字节大小;
    A  是 Cardinal 类型, 也应该是 4  字节大小;
    B  是 Word     类型, 应该是   2  字节大小;
    合计为                        10 个字节.
  }

  {可事实, TpersonRec 只有 8 个字节}
  ShowMessage(IntToStr(SizeOf(TpersonRec))); {8}

  {
    原因是: 字段 A 和 字段 B 公用了一个储存空间;
    当然这个储存空间得依着大的, 是 Cardinal 的尺寸 4 个字节.
  }


//赋值测试:
  personRec.ID := 110;
  personRec.A  := 100000{一看就知道是个股东}

//取值:
  ShowMessage(IntToStr(personRec.A)); {100000; 这不可能有错, 十万大洋}

//但是:
  ShowMessage(IntToStr(personRec.B)); {34464 ?! 难道这是工人的日薪吗?}
  {
    首先, A 和 B 两个字段占用同一个空间, 给其中一个赋值, 另一个当然也就有值了;
    但因为数据类型的容量不同, 它们的值有可能是不一样的.
    在很多情况下, 我们可能根本不去理会另一个值, 但如果的确需要呢?
    看下一个例子:
  }

end;



type
  TpersonRec = record
    ID: Integer;
    case tag: Boolean of    {在这里加了一个 tag 变量}
      True:  (A: Cardinal);
      False: (B: Word);
  end;
var
  personRec: TpersonRec;
begin
  {我们可以用 tag 变量来区分, 记录中变体部分的值到底是谁的, 譬如:}
  personRec.ID  := 110;
  personRec.tag := True;
  personRec.A   := 100000{股东的的年薪}

  personRec.ID  := 111;
  personRec.tag := False;
  personRec.B   := 100;    {工人的日薪}
end;



//最经典的变体结构莫过于 Delphi 定义的 TMessage 结构了, 两组数据分分合合都是一体, 多么巧妙啊!

TMessage = packed record
    Msg: Cardinal;
    case Integer of
      0: (
        WParam: Longint;
        LParam: Longint;
        Result: Longint);
      1: (
        WParamLo: Word;
        WParamHi: Word;
        LParamLo: Word;
        LParamHi: Word;
        ResultLo: Word;
        ResultHi: Word);
  end;

分享到:
评论

相关推荐

    DELPHI中的记录类型【存储方式和变体记录】.mht

    DELPHI中的记录类型【存储方式和变体记录】.mht

    delphi读写取流记录文件TFileStream

    delphi读写取流记录文件TFileStream img格式图片追加存储

    delphi· 如何以参数化方式查询记录

    delphi· 如何以参数化方式查询记录的详细例子,对初学者很有帮助。,

    实例Delphi演示过程采用指针的形式存储

     示例中使用Rec记录来存储两个值,其中Rec.Proc是过程类型。然  后代码中使用一个PInteger类型的指针来访问记录的两个域。    在访问Rec.Proc域时,可以得到指向TestProc()过程的指针。这表  明:过程类型...

    简单的Delphi销售记录查询程序.rar

    简单的Delphi销售记录查询程序模块代码,带数据库文件,db数据库,其实是一个销售记录浏览程序,可上一条、下一条浏览数据库中存储的销售记录,可应用到你的数据库系统中。

    Delphi6数据库开发典型实例

    第 8 章介绍了基于数据库的闹铃程序设计,该实例的特点在于程序界面的背景和程序的声音文件均存储在数据库中,其中涉及到3 种数据库存储方式,即简单数据存储(如字符串和整型数等)、图像数据存储和声音文件存储。...

    Delphi7 编程 100 实例

    ToolBar工具栏控件的使用 动态建立主菜单选项 窗口界面的动态分隔条...存储过程 数据模块的同步显示 建立Web服务的数据提供端 建立Web服务的数据访问端 开发WebSnap数据库程序 建立ActiveForm数据...

    Delphi编程100例

    全部实例代码。目录如下: ...Delphi中的ini文件的读写 建立键盘鼠标动作记录与回放 实现指定目录下的文件查询 实现对系统的操作监视 系统级热键的实现 检测NumLock、Insert、CapsLock、ScrollLock键的状态

    Delphi7编程100例

    ToolBar工具栏控件的使用 ... Delphi中的ini文件的读写 建立键盘鼠标动作记录与回放 实现指定目录下的文件查询 实现对系统的操作监视 系统级热键的实现 检测NumLock、Insert、CapsLock、ScrollLock键的状态

    Delphi5开发人员指南

    11.1.2 在Delphi程序中使用多线程 304 11.1.3 关于线程的滥用 305 11.2 TThread对象 305 11.2.1 TThread基础 305 11.2.2 TThread实例 307 11.2.3 线程的终止 307 11.2.4 与VCL同步 308 11.2.5 一个演示程序 310 ...

    《Delphi7编程100例》代码

    ToolBar工具栏控件的使用动态建立主菜单选项窗口界面的动态分隔条动态设置...存储过程数据模块的同步显示建立Web服务的数据提供端建立Web服务的数据访问端开发WebSnap数据库程序建立ActiveForm数据浏览建立数据查询Web...

    delphi EhLib 9.5.012 Full Source 专业版 .rar

    允许以树的方式进行记录。每条记录可以有一条记录 元素分支和本身是其他父母记录的元素。 组件TDBGridEh支持显示这些组件的树型结构 记录。 允许连接到其他TMemTableEh的内部阵列(通过 ExternalMemData...

    Delphi实现带记忆播放记录的音乐播放器

    使用Delphi语言编写一个带记忆功能的音乐播放器,也就是可以保留打开的音乐文件播放记录,历史记录存储于INI文件中,这也是使用相当方便的一种模式,本例所要展现的功能是播放记录保存的功能,因此在播放器本身的...

    Delphi5数据库开发技术

    30312.1.2 应用程序的结构设计 30512.2 应用程序中数据模块的设计 30512.3 用户登录功能的实现 30612.4 图书馆管理系统功能的实现 30812.4.1 修改图书记录 30912.4.2 修改学生记录 31112.4.3 修改密码设置 31312.4.4...

    Delphi 5编程实例与技巧

    12.3.1 存储过程 252 12.3.2 触发器 252 12.4 本地缓存 253 第13章 Web与数据库 260 13.1 CGI的工作原理 260 13.2 Delphi对CGI的支持 260 13.3 创建Web应用程序 261 13.4 表单 262 13.5 把信息保存到数据库 264 13.6...

    delphi仓库管理系统

    也可以分开编程,程序名以“班级+座号+(表示程序名的中英文信息)”来命名,同一单号中进出仓单号、进出仓日期、操作人员必须完全相同,同一单号中不能进仓与出仓同时存在,通过调用存储过程完成进出仓操作。...

    Delphi结构类型-全

    结构类型包括集合、数组、记录,也包括类、类引用(class-reference) 和接口类型。除了集合只能包含有序值以外,结构类型可以包含其它的结构类型,且结构的层次不受限 制。 默认情况下,一个结构类型的值被圆整为字...

    Delphi开发范例宝典目录

    实例270 向SQL Server中存储Word文档 348 实例271 从SQL Server中提取Word文档 349 8.4 SQL Server服务器应用 350 实例272 和服务器时间同步 350 实例273 取得网络中的SQL服务器名 351 8.5 数据库维护 ...

    DELPHI 5编程实例与技巧

    Delphi是由Inprise公司推出的面向对象的可视化软件开发工具。Delphi 5是Delphi的最新版本。本书共分三部分、16章,主要介绍Delphi 5集成开发环境,对象Pascal语言、组件、通用编程技术、动态链接库、多线程、多媒体...

Global site tag (gtag.js) - Google Analytics