数据类型及其相互关系

来源:互联网 发布:mac os官方壁纸 编辑:程序博客网 时间:2024/05/21 18:34

3.1数据类型及其相互关系

本节对object pascal的数据类型做全面的介绍,并揭示各种数据类型的内存管理方法,最后讨论他们相互的兼容关系和转化方法。

目的:能对各种数据类型有比较全面的,深入的认识,并掌握他们相互关系,最终能在编程的时能合理的准确的选择使用他们

 

3.1.1数据类型概述

       Object pascal中定义啦大量的数据类型,不同数据类型具有不同的用途。虽然delphi中对数据类型比较严格,但他们之间也不是严格划清界限的,也就是说,某些数据类型之间具有兼容性和转化性。

       下边给个数据类型全家福。

Simple

 

 

Ordinal

有序类型

 

 

 

类型

取值范围

空间

 

 

Integer

 

 

 

 

 

 

Integer

-2147483648~2147483647

Signed32-bit

 

 

 

Cardinal

0~4294967295

Unsigned32-bit

 

 

 

Shortint

-128~127

Signed8-bit

 

 

 

Smallint

-32726~32767

Signed16-bit

 

 

 

Longint

-2147483648~2147483647

Signed32-bit

 

 

 

Int64

-2^63~2^63-1

Signed64-bit

 

 

 

Byte

0~255

Unsigned8-bit

 

 

 

Word

0~65535

Unsigned16-bit

 

 

 

Longword

0~4294967295

Unsigned32-bit

 

 

Character

 

 

 

 

Char

Ansichar

Widechar

 

 

Boolean

 

 

 

 

Boolean

Bytebool

Longbool

Wordbool

 

Enumerated

 

 

 

Subrange

 

 

Real

 

 

 

类型

精度

取值范围

空间

 

 

Real

15-16

5.0*10^-324~1.7*10^308

8B

 

 

*real48

11-12

2.9*10^39~1.7*10^38

6B

 

 

Single

7-8

1.5*10^45~3.4*10-38

4B

 

 

Double

15-16

5.0*10^-324~1.7*10^308

8B

 

 

Extended

19-20

3.6*10^-4951~1.1*10^4932

10B

 

 

*comp

19-20

-2^63+1~2^63-1

8B

 

 

Currency

19-20

 

8B

String

`

 

*shortstring

Pchar

Pansichar

ansiString widestring

Pwidechar

Structured

 

 

Set

Array

Record

Classclass reference interface

File

Pointer

 

 

无类型指针

有类型指针

 

Procedural

 

 

普通过程类型

对象过程类型

 

Variant

 

 

Variant

Olevariant

 

1,  ordinal(有序)类型

simple类型规定啦一个数据取值范围。而ordinal类型在此基础上,还增加啦有序的特性。

 

 

该部分演示代码:

var

  B: Byte;

begin

  B := 255;

  {$R+} //执行越界检查。此时越界会抛出erangeerror类型的异常。

  B := B + 1;

  {$R-}//不执行越界检查,这是默认状态。此时不会抛出错误,但会得到错误的运算结果。

       //看下例代码

  ShowMessage(IntToStr(B));

end;

======================================================================var

  B: Byte;      //Byte类型的变量在内存中占据8Bit。使用函数SizeOf可以取得一个变量或者一个类型在内存中占据的字节数

begin

  B := 255;    //此时B在内存中的状态是:111111118位都是1)。

  B := B + 1; //期望获得:100000000(最高位是1,其他8位是0);但是Byte最多8位,所以最高位被抛弃,因而得到低8位全0,也就是最终结果0

  ShowMessage(IntToStr(B));      //得到B=0而不是256

end;

======================================================================

type

  TC = 'A'..'Z';       //定义字符内容的子界类型

var

  C: TC;       

  OI: Integer;

  PI, SI, H, L: Char;

  S: String;

begin

  C := 'B';

  OI := Ord(C);     //OI = 66

//ord 取得有序变量的值在取值范围中所在的顺序(即位置)

  PI := Pred(C);    //PI = ‘A’

//pred 取得有序变量的前序的值(即上一个位置的值)

  SI := Succ(C);    //SI = ‘C’

//succ 取得有序变量的后序的值(即下一个位置的值)

  H := High(TC);  //或者H := High(C);     H = Z

//high。。末序的值(取值范围规定的最大的值)

  L := Low(TC);    //或者L := Low(C);       L = A

//low ..始序的值。。

  S :=

    '顺序:' + IntToStr(OI) + #13 +

    '前序:' + PI + #13 +

    '后序:' + SI + #13 +

    '末序:' + H  + #13 +

    '始序:' + L;

  ShowMessage(S);

end;

 

 

 

Integer的基本类型是integercardinal,建议大多情况下使用这两中类型,因为他们呢是32位的,操作系统和cpu可以花费最少的时间处理他们。

其中取值范围大的可以兼容取值范围小的。范围大的可以赋值给范围小的,单数据会被斩断,这个规则对于实数也是适用的。

 

 

代码分析:

 

var

  B: Byte;      //B8位的

  W: Word;    //W16位的

begin

  W := $1234;       //16进制常数$1234赋值给W

  B := W;      //B得到的值是W的低8位,即16进制的$34,也即10进制的52

  ShowMessage(IntToStr(B));      //显示B的结果值52

end;

Character的基本类型是char

Boolean的基本类型是boolean

Enumerated(枚举)类型定义拉一系列有序值的集合。Enumerated变量就从这个既定的集合中取某个值。集合中的有序值称为元素,元素一般从0开始连续索引

如下代码分析:

type

  TSize = (Small, Medium, Large);

var

  Size: TSize;

begin

  Size := Large;

  ShowMessage(IntToStr(Ord(Size)));        //显示2

end;

Subrange(子界)类型也是定义一系列有序值的集合。

代码分析:

type

  TColors = (Red, Blue=5, Green, Yellow, Orange, Purple=10, White, Black);        //定义一个枚举类型TColorsTColors

义了一些有序值供下面的子界类型TMyColors使用

  TMyColors = Green..White;

var

  MyColors: TMyColors;

begin

  MyColors := Green;   // MyColors只能在GreenWhite之间取值,取RedBlack等是不允许的

  ShowMessage(IntToStr(Ord(MyColors)));              //显示6,因为元素GreenTColors中被索引为6

end;

 

 

2.real(实数)类型

因为无理数的介入,使得real不再能够“有序”。

Real的基本类型是real,。

3.string(字符串)类型

分为三类:短字符串,长字符串,宽字符串。

Shortstring在内存中占0.。。255字符。就是说他被固定为256字节。其中第0字节存储字符串的实际长度。

长字符串和宽字符串的内存分配是动态的,最大可到2GB,可以认为他们是无限长的。

4.structured(构造)类型

Array(数组)有两种形式:静态数组和动态数组。

Record(记录)类型,十多个任意元素的集合,其中的元素成为记录的字段。

File(文件)类型用来读写文件。

剩下的构造类型class。。三种子类型,由于牵涉的东西比较多,在后边用到时再说他们。

5.pointer(指针)类型

一个指针占用4字节空间,该内存块用来存储另一块内存所在的地址,这另一块内存区才是存储实际数据的地方。

6.procedural(过程)类型

算是一种比较特殊的类型。这种变量可以存取一个过程或者函数!。可以实现回调函数的功能。

结合代码分析啊。(看ij最终是否一样)

type 

  TOneFun = function(X: Integer): Integer;        //声明一个过程类型

 

function SomeFunction(X: Integer): Integer;              //实现一个和TOneFun兼容的过程

begin

  Result := X*2;

end;

 

function SomeCallBack(X: Integer; OneFun: TOneFun): Integer;      //SomeCallBack被调用时,回调函数OneFun,并返回OneFun的执行结

begin

  Result := OneFun(X);

end;

 

procedure TForm1.Button1Click(Sender: TObject);

var

  F: TOneFun;      //声明过程类型变量,也可以直接声明:F: function(X: Integer): Integer;

  I,J: Integer;

begin

  F := SomeFunction;   //用过程类型变量F引用一个实际过程

  I := F(4);                  //通过过程类型变量F直接调用函数SomeFunction

  J := SomeCallBack(4, F);  //通过过程类型变量F回调函数SomeFunction

  if I = J then

    ShowMessage('F(4)SomeCallBack功能相同');

end;

7.variant(可变)类型

       可以存储绝大部分不同的类型的数据。

       某个时刻有三种可能的状态:unassigednull,非null

记住不要对null状态的variant变量进行操作。否则抛出evariantInvalidOpError类型的错误。

比如:

 

以上已全面的叙述啦object pascal中的数据类型。

 

 

3.1.2 变量的内存分配和释放

变量的内存分配有两种形式:自动和人工。自动分配:声明变量后被分配内存;人工:声明变量后必须用代码显式的分配内存。

       如果是非指针类型的全局变量或局部变量声明后会自动分配内存。

       如果是指针类型的则不会自动分配内存。如果是全局的初始值是nil,表示没有指向;如果是局部的,尽管没有分配内存,但是会随机地指向一个地址,值不是nil

      

变量的释放:。。。

具体分配的方法有:

       1.赋值。

       比如:

var

  P1,P2: PChar;

begin

  P1 := 'lxpbuaa';   {P1已经拥有一块内存}

  P2 := P1;                  {P2指向P1的内存,这样就间接完成了P2的内存分配}

end;

       2.对于类,则调用构造函数。

       比如:

      

var

  Obj: TObject;

begin

  Obj := TObject.Create;      //调用构造函数创建对象,变量Obj指向该对象

  Obj.Free;                         //释放内存,Free内部调用析构函数Destroy;也可以使用:

  //FreeAndNil(Obj);

end;

       3.分配指定大小的内存。

var

  P: PChar;

  Size: Cardinal;

begin

  Size := MAX_COMPUTERNAME_LENGTH + 1;

  GetMem(P, Size);      //分配Size个字节的内存块(即缓冲区),并让P指向它

  GetComputerName(P, Size);     //API函数GetComputerName将取得的计算机名放在P

  ShowMessage(P);

  FreeMem(P);             //释放缓冲区占用内存

end;

 

结下,动态分配内存的函数和过程。

       1.Getmem

       2.Allocmem

       Reallocmem

Freemem

3.New

 

 

3.1.3 数据的内存结构

       分析数据类型变量在内存中的真实存放格式,目的:了解这些类型的真是运作方式。

1.       boolean类型

2.       enumerated类型

3.       ansistring/string类型

包括四个域:

偏移/byet

 内容

-8

存储引用计数

-4

存储字符长度

0..Length-1

存储实际字符

Length

零字符(null或者#0)。

引用计数域帮助管理内存的自动释放工作。

零字符域便于和pchar类型的转化。

Widestring变量是类似的,但是少啦引用计数域。

Ansistringwidestring都用4byet(即32Bits)来存储字符长度,

代码演示:

var

  S: String;

  L: Integer;

begin

  S := 'lxpbuaa';

  L := PInteger(Integer(S) - 4)^;

  //或者 L := PInteger(PInteger(@S)^ - 4)^;

  //或者 L := PInteger(PInteger(Addr(S))^ - 4)^;

  //最终得到L = Length(S) = 7;

end;

4.       set类型

5.       dynamic array类型

动态数组内存被分为几个域:

偏移/byet

 内容

-8

存储引用计数

-4

存储元素数目

0..Length*(元素的大小)-1

存储存储元素值

6.       Variant类型

Variant内部存储为TVarData类型的记录。TVarData被定义在system单元。

Vtype用来存储数据的类型。

        另外一个字段为8字节大小,用来存储实际数据或者指向该实际数据的指针。

根据这两个字段,一个variant可以和其他数据类型相互转化。

 

 

3.1.4强数据类型与类型转化

       Object pascal十一种“强数据类型”语言。就是严格区分不同的数据类型并不总是允许不同类型数据直接赋值。

。。。

       数据类型转化的方法

1.       typecasting(类型强制转化)

2.       pointers(指针)

3.       variants(可变类型)

4.       variant parts in records(变体记录):不做介绍用到时讨论

5.       absolute addressing(绝对地址):同上

 

 

关于过程和函数,类等等在下节介绍。

 

原创粉丝点击