数据类型及其相互关系
2008-10-28 20:04
507 查看
3.1[/b]数据类型及其相互关系[/b][/b]
本节对object pascal的数据类型做全面的介绍,并揭示各种数据类型的内存管理方法,最后讨论他们相互的兼容关系和转化方法。
目的:能对各种数据类型有比较全面的,深入的认识,并掌握他们相互关系,最终能在编程的时能合理的准确的选择使用他们
3.1.1[/b]数据类型概述[/b][/b]
Object pascal中定义啦大量的数据类型,不同数据类型具有不同的用途。虽然delphi中对数据类型比较严格,但他们之间也不是严格划清界限的,也就是说,某些数据类型之间具有兼容性和转化性。
下边给个数据类型全家福。
1, ordinal(有序)类型
simple类型规定啦一个数据取值范围。而ordinal类型在此基础上,还增加啦有序的特性。
Integer的基本类型是integer和cardinal,建议大多情况下使用这两中类型,因为他们呢是32位的,操作系统和cpu可以花费最少的时间处理他们。
其中取值范围大的可以兼容取值范围小的。范围大的可以赋值给范围小的,单数据会被斩断,这个规则对于实数也是适用的。
代码分析:
Character的基本类型是char。
Boolean的基本类型是boolean
Enumerated(枚举)类型定义拉一系列有序值的集合。Enumerated变量就从这个既定的集合中取某个值。集合中的有序值称为元素,元素一般从0开始连续索引
如下代码分析:
Subrange(子界)类型也是定义一系列有序值的集合。
代码分析:
2.real(实数)类型
因为无理数的介入,使得real不再能够“有序”。
Real的基本类型是real,。
3.string(字符串)类型
分为三类:短字符串,长字符串,宽字符串。
Shortstring在内存中占0.。。255字符。就是说他被固定为256字节。其中第0字节存储字符串的实际长度。
长字符串和宽字符串的内存分配是动态的,最大可到2GB,可以认为他们是无限长的。
4.structured(构造)类型
Array(数组)有两种形式:静态数组和动态数组。
Record(记录)类型,十多个任意元素的集合,其中的元素成为记录的字段。
File(文件)类型用来读写文件。
剩下的构造类型class。。三种子类型,由于牵涉的东西比较多,在后边用到时再说他们。
5.pointer(指针)类型
一个指针占用4字节空间,该内存块用来存储另一块内存所在的地址,这另一块内存区才是存储实际数据的地方。
6.procedural(过程)类型
算是一种比较特殊的类型。这种变量可以存取一个过程或者函数!。可以实现回调函数的功能。
结合代码分析啊。(看i和j最终是否一样)
7.variant(可变)类型
可以存储绝大部分不同的类型的数据。
某个时刻有三种可能的状态:unassiged,null,非null
记住不要对null状态的variant变量进行操作。否则抛出evariantInvalidOpError类型的错误。
比如:
以上已全面的叙述啦object pascal中的数据类型。
3.1.2[/b] [/b]变量的内存分配和释放[/b][/b]
变量的内存分配有两种形式:自动和人工。自动分配:声明变量后被分配内存;人工:声明变量后必须用代码显式的分配内存。
如果是非指针类型的全局变量或局部变量声明后会自动分配内存。
如果是指针类型的则不会自动分配内存。如果是全局的初始值是nil,表示没有指向;如果是局部的,尽管没有分配内存,但是会随机地指向一个地址,值不是nil。
变量的释放:。。。
具体分配的方法有:
1.赋值。
比如:
2.对于类,则调用构造函数。
比如:
3.分配指定大小的内存。
结下,动态分配内存的函数和过程。
1.Getmem
2.Allocmem
Reallocmem
Freemem
3.New
3.1.3 数据的内存结构
分析数据类型变量在内存中的真实存放格式,目的:了解这些类型的真是运作方式。
1. boolean类型
2. enumerated类型
3. ansistring/string类型
包括四个域:
引用计数域帮助管理内存的自动释放工作。
零字符域便于和pchar类型的转化。
Widestring变量是类似的,但是少啦引用计数域。
Ansistring和widestring都用4个byet(即32Bits)来存储字符长度,
代码演示:
4. set类型
5. dynamic array类型
动态数组内存被分为几个域:
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(绝对地址):同上
关于过程和函数,类等等在下节介绍。
本节对object pascal的数据类型做全面的介绍,并揭示各种数据类型的内存管理方法,最后讨论他们相互的兼容关系和转化方法。
目的:能对各种数据类型有比较全面的,深入的认识,并掌握他们相互关系,最终能在编程的时能合理的准确的选择使用他们
3.1.1[/b]数据类型概述[/b][/b]
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 | |||||
simple类型规定啦一个数据取值范围。而ordinal类型在此基础上,还增加啦有序的特性。
该部分演示代码: var B: Byte; begin B := 255; {$R+} //执行越界检查。此时越界会抛出erangeerror类型的异常。 B := B + 1; {$R-}//不执行越界检查,这是默认状态。此时不会抛出错误,但会得到错误的运算结果。 //看下例代码 ShowMessage(IntToStr(B)); end; ======================================================================var B: Byte; //Byte类型的变量在内存中占据8个Bit。使用函数SizeOf可以取得一个变量或者一个类型在内存中占据的字节数 begin B := 255; //此时B在内存中的状态是:11111111(8位都是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; |
其中取值范围大的可以兼容取值范围小的。范围大的可以赋值给范围小的,单数据会被斩断,这个规则对于实数也是适用的。
代码分析:
var B: Byte; //B是8位的 W: Word; //W是16位的 begin W := $1234; //将16进制常数$1234赋值给W B := W; //B得到的值是W的低8位,即16进制的$34,也即10进制的52 ShowMessage(IntToStr(B)); //显示B的结果值52 end; |
Boolean的基本类型是boolean
Enumerated(枚举)类型定义拉一系列有序值的集合。Enumerated变量就从这个既定的集合中取某个值。集合中的有序值称为元素,元素一般从0开始连续索引
如下代码分析:
type TSize = (Small, Medium, Large); var Size: TSize; begin Size := Large; ShowMessage(IntToStr(Ord(Size))); //显示2 end; |
代码分析:
type TColors = (Red, Blue=5, Green, Yellow, Orange, Purple=10, White, Black); //定义一个枚举类型TColors。TColors定 义了一些有序值供下面的子界类型TMyColors使用 TMyColors = Green..White; var MyColors: TMyColors; begin MyColors := Green; // MyColors只能在Green…White之间取值,取Red、Black等是不允许的 ShowMessage(IntToStr(Ord(MyColors))); //显示6,因为元素Green在TColors中被索引为6 end; |
因为无理数的介入,使得real不再能够“有序”。
Real的基本类型是real,。
3.string(字符串)类型
分为三类:短字符串,长字符串,宽字符串。
Shortstring在内存中占0.。。255字符。就是说他被固定为256字节。其中第0字节存储字符串的实际长度。
长字符串和宽字符串的内存分配是动态的,最大可到2GB,可以认为他们是无限长的。
4.structured(构造)类型
Array(数组)有两种形式:静态数组和动态数组。
Record(记录)类型,十多个任意元素的集合,其中的元素成为记录的字段。
File(文件)类型用来读写文件。
剩下的构造类型class。。三种子类型,由于牵涉的东西比较多,在后边用到时再说他们。
5.pointer(指针)类型
一个指针占用4字节空间,该内存块用来存储另一块内存所在的地址,这另一块内存区才是存储实际数据的地方。
6.procedural(过程)类型
算是一种比较特殊的类型。这种变量可以存取一个过程或者函数!。可以实现回调函数的功能。
结合代码分析啊。(看i和j最终是否一样)
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; |
可以存储绝大部分不同的类型的数据。
某个时刻有三种可能的状态:unassiged,null,非null
记住不要对null状态的variant变量进行操作。否则抛出evariantInvalidOpError类型的错误。
比如:
以上已全面的叙述啦object pascal中的数据类型。
3.1.2[/b] [/b]变量的内存分配和释放[/b][/b]
变量的内存分配有两种形式:自动和人工。自动分配:声明变量后被分配内存;人工:声明变量后必须用代码显式的分配内存。
如果是非指针类型的全局变量或局部变量声明后会自动分配内存。
如果是指针类型的则不会自动分配内存。如果是全局的初始值是nil,表示没有指向;如果是局部的,尽管没有分配内存,但是会随机地指向一个地址,值不是nil。
变量的释放:。。。
具体分配的方法有:
1.赋值。
比如:
var P1,P2: PChar; begin P1 := 'lxpbuaa'; {P1已经拥有一块内存} P2 := P1; {将P2指向P1的内存,这样就间接完成了P2的内存分配} end; |
比如:
var Obj: TObject; begin Obj := TObject.Create; //调用构造函数创建对象,变量Obj指向该对象 Obj.Free; //释放内存,Free内部调用析构函数Destroy;也可以使用: //FreeAndNil(Obj); end; |
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变量是类似的,但是少啦引用计数域。
Ansistring和widestring都用4个byet(即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; |
5. dynamic array类型
动态数组内存被分为几个域:
偏移/byet | 内容 |
-8 | 存储引用计数 |
-4 | 存储元素数目 |
0..Length*(元素的大小)-1 | 存储存储元素值 |
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(绝对地址):同上
关于过程和函数,类等等在下节介绍。
相关文章推荐
- Unicode数据类型(与ANSI关系和相互转化)
- java简单数据类型中各类型数据间的优先关系和相互转换
- 简要介绍TAO支持的IDL数据类型及其C++ Mapping关系。
- 黑马程序员——Java基本数据类型及其相互转换
- 高效掌握C#第一回---C#中的基本数据类型及其相互转换
- ASP.NET Web API 数据提供系统相关类型及其关系
- Unicode数据类型(与ANSI关系和相互转化)
- Unicode数据类型(与ANSI关系和相互转化)
- Unicode数据类型(与ANSI关系和相互转化)
- Unicode数据类型(与ANSI关系和相互转化)
- Java八种基本数据类型的比较及其相互转化
- ATL中常见数据类型及其相互转换
- Access, SQL Server, and Oracle数据类型的对应关系
- Java中数据类型及其之间的转换(转)
- C语言中的数据类型及其转换详解
- flex 和java数据类型匹配关系
- matlab中用imshow()显示图像与图像矩阵的数据类型的关系
- ffmpeg主要数据结构及其之间的关系
- Java学习6——基本数据类型及其转换
- python语言基础之基本数据类型及其运算(1)