zoukankan      html  css  js  c++  java
  • DELPHI中的记录类型【存储方式和变体记录】(record)

    一、DELPHI中记录的存储方式
          在DELPHI中,我们用record关键字来表明一个记录,有时候,我们还会看到用packed record来声明的记录,这二者的区别就在于存储方式的不同。
          在windows中,内存的分配一次是4个字节的,而Packed按字节进行内存的申请和分配,这样速度要慢一些,因为需要额外的时间来进行指针的定位。因此如果不用Packed的话,Delphi将按一次4个字节的方式申请内存,因此如果一个变量没有4个字节宽的话也要占4个字节!这样浪费了一些空间,但提高了效率。所谓鱼与熊掌不可兼得。
           例如一个记录,以,sizeof(wudi)应该得到8。而如果使用packed关键字,那么sizeof(wudi)则得到5。

       type wudi= record
         age integer;
         sex shortint;    
       end;


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

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

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

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


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

      2.2使用变体记录时要注意: 
    (1)Long  String、WideString、Dynamic  Array、Interface的大小都是指针大小,  OleVariant其实就是COM  SDK中的VARIANT结构,大小是16字节。但在Object  Pascal中它们都需要自动终结化,如果它们出现在variant  part中,编译器就无法知道它们是否应该进行终结化――因为不知道当前存储的是哪种类型。   
    (2)所有变体字段共享一段内存。而共享内存的大小则由最大变体字段决定。 
    (3)当tag存在时,它也是记录的一个字段。也可以没有tag。 
    (4)记录的变体部分的条件域必须是有序类型
    (5)记录类型中可以含有变体部分,有点象case语句,但没有最好的end,变体部分必需在记录中其他字段的声明之后

      2.3变体记录得作用
    (1)节约空间。对于那些要根据条件而决定是否存储得类型,完全可以利用变体记录来达到节约空间得效果。例如,一个公司的员工薪水可以是月薪、年薪等方式,那么并没有必要在记录中都分配空间而又用不到。
    (2)类型的转换。例如,如果有一个64位的整数类型作为变体的第一个字段,一个32位的整数Integer类型作为另一个变体的第一个字段,那么可以向64字段赋值然后以整数Integer字段读出其前32位
    (3)妙用还有很多,根据它的原理挖掘吧

       2.4一个演示变体记录使用的例子     

    {
        作者    :wudi_1982
        联系方式:wudi_1982@hotmail.com
        转载请著名出处
    }

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs,typinfo, StdCtrls, ComCtrls, ExtCtrls;

    type
      WdFileType 
    = (Files, Dirs);//类型信息
      TWdFileInfo 
    = record//一个变体记录
        Fname: string[10];//文件名
        case typeid:WdFileType of//根据是文件夹还是文件来决定
          Files (Fsize integer);//文件大小
          Dirs  (Dsize             integer;//文件夹大小
                   ContainFileCount integer;//包含文件的个数
                   ContainDirCount  integer);//包含文件夹的个数
      end;
      TForm1 
    = class(TForm)
        Memo1: TMemo;
        Panel1: TPanel;
        Button1: TButton;
        GroupBox1: TGroupBox;
        Label1: TLabel;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      
    private
        pp array[
    0..1of TWdFileInfo;//一个变体记录数组
        procedure ShowInfo;  //在memo中显示当前变体记录的信息
      public
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      
    //初始化是为记录赋值
       with pp[0do
       begin
         Fname :
    = 'PP0';
         typeid :
    = Files;
         
    //fsize和dsize实际用的是同一块存储空间,
         
    //这里两个都赋值了,存储空间中记录的自然是后者
         Fsize := 10;
         Dsize :
    = 100;
         ContainFileCount :
    = 1;
         ContainDirCount :
    = 2;
       end;
       with pp[
    1do
       begin
         Fname :
    = 'PP1';
         typeid :
    = Dirs;
         Fsize :
    = 0;
         Dsize :
    = 100;
         ContainFileCount :
    = 11;
         ContainDirCount :
    = 222;
       end;
       Memo1.Clear;
       ShowInfo;
    end;

    procedure TForm1.ShowInfo;
    var
     integer;
     fs 
    string;
    begin
       Memo1.Lines.Add(
    '变体记录信息显示');
       
    for := 0 to 1 do
       begin
         fs :
    = Format('PP%d的大小是(%d)'+#13+'Fsize:(%d),Dsize:(%d)'+#13+'ContainFileCount:(%d),CDirCount:(%d);'
         ,[i,
    sizeof(pp[i]),pp[i].Fsize,pp[i].Dsize,pp[i].ContainFileCount,pp[i].ContainDirCount]);
       Memo1.Lines.Add(fs);
       Memo1.Lines.Add(
    '------------------------');
       end;


    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Clear;
    end;

    end.
  • 相关阅读:
    基本MVVM 和 ICommand用法举例(转)
    WPF C# 命令的运行机制
    628. Maximum Product of Three Numbers
    605. Can Place Flowers
    581. Shortest Unsorted Continuous Subarray
    152. Maximum Product Subarray
    216. Combination Sum III
    448. Find All Numbers Disappeared in an Array
    268. Missing Number
    414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254657.html
Copyright © 2011-2022 走看看