DELPHI学习---简单类型
Object Pascal数据类型的分类:
simple
ordinal
integer
character
boolean
enumerated
subrange
real
string
structured
set
array
record
file
class
class reference
interface
pointer
procedural
variant
Integer types (整数类型)
integer 32位有符号
cardinal 32位无符号
shortint 8位有符号
smallint 16位有符号
longint 32位有符号
int64 64位有符号
byte 8位无符号
word 16
longword 32
Character types (字符类型)
char 相当于ansichar
ansichar 8位字符集
widechar 依据unicode字符集
Boolean types (布尔类型)
boolean 为首选,值由内置的常数True和False来表示.
bytebool
wordbool
loogbool
Enumerated types (枚举类型)
枚举类型定义一个有次序的值的集合:这些值用标志符表示,并被列举出来,但它们并没有内在的含义.
type typename=(val1,..,valn); //用括号定义枚举
type suit=(club,diamond,heart,spade);
var
card1:suit;
card2:suit;
subrange types (子界类型)
子界类型表示其它有序类型(称为基础类型)的一个子集:它的形式为Low..High,
type TColors=(Rea,Blue,Green,Yellow,Orange,Purple,White,Black);
你就可以这样定义一个了界类型:
type TMyColors=Green..White;
这里,TMyColors就包含值Green,Yellow,Orange,Purple和White.
能用数字常量和字符(长度为1的字符串)定义子界类型:
type
SomeNumbers=-128..127; //不用括号,直接Low..High形式
Caps='A'..'Z';
还可以这样:
var SomeNum:1..500;
Real type (实数类型)
real48 6字节
single 4字节
double 8
extended 10
comp 8
currency 8
一般实数类型为real,在当前实现中,它相当于double.
String types (字符串类型)
类型 最大长度 所需内存(字节) 用于
shortstring 255个字符 2-256 向后兼容
ansistring 2^31 4-2GB 8位(ANSI)字符
widestring 2^30个字符 4-2GB Unicode字符
ansistring,有时称为长字符串,在大多数情况下是首选类型.
var S:string; --在默认的{$H+}状态下,编译器把string解释为ansistring,{$H-}解释为shortstring;
你可以像数组一样对字符串使用索引。若S 是一个字符串变量,i 是一个整数表达式,则S[i]表示S 中第
i 个字符(或者,严格说来,是第i 个字节)。对于ShortString 或AnsiString,S[i]是AnsiChar 类型;对于
WideString,S[i]是WideChar 类型。
语句 MyString[2] := 'A'; 把值A 赋给MyString 的第2 个字符。
Short strings(短字符串)
一个ShortString 可包含0 到255 个字符。它的长度能动态改变,它被静态分配256 字节的内存:第1 个
字节存储串的长度,剩下的255 个字节存储字符。若S 是一个ShortString 变量,Ord(S[0]),和Length
(S)一样,将返回S 的长度;给S[0]赋值,就像调用SetLength,将改变S 的长度。ShortString 使用8
位ANSI 字符,保留它只是为了向后兼容性。
Object Pascal 支持short-string 类型(实际上,它是ShortString 的子类型),它的最大长度可以是从0 到
255 之间的任何值。它通过在保留字string 的后面添加一对包含数字的中括号来声明。比如
var MyString: string[100];
声明一个叫做MyString 的变量,它的最大长度是100 字节,这和以下的声明效果相同
type CString = string[100];
var MyString: CString;
像这样声明的变量,它们只分配所需的内存,也就是指定的最大长度加上一个字节。在我们的例子中,
MyString 使用101 个字节,相比之下,使用内置的ShortString 类型将分配256 个字节。
当给一个short-string 变量赋值时,多于它最大长度的部分将被截取掉。
标准函数High 和Low 能作用于short-string 类型名和变量,High 返回它的最大长度,Low 返回0。
Long strings(长字符串)
AnsiString 类型又称为长字符串,它可以动态分配,并且长度只受内存限制。它使用8 位ANSI 字符。
长串变量是一个指针,占据4 个字节的内存。当变量为空时(也就是长度为0 的字符串),指针为nil,
此时,它不需要额外的内存;当变量为非空时,它指向一个动态分配的内存块,内存块存储字符串的值:
一个32 位的长度指示器,一个32 位的引用计数器。它的内存在堆中分配,但它的管理是完全自动的,
不需要自己编写代码。
因为长串变量是指针,所以,两个或更多的变量可以引用同一个值,而不必使用额外的内存。编译器利
用这一点节省资源和进行快速赋值。只要一个长串变量被销毁或赋给一个新值,原来的串(变量的前一
个值)引用计数减1,而新的值(如果有的话)引用计数加1。若引用计数为0,它的内存被释放。这个
过程被称为reference-counting。当使用字符串索引改变其中的一个字符时,若字符串的引用计数大于1,
将生成串的一个拷贝,这被称为copy-on-write 机制。
WideString(宽字符串)
WideString 类型是动态分配的、由16 位Unicode 字符所构成的字符串。在大多数方面,它和AnsiString
相似。(注:宽字符串没有引用计数,不支持copy-on-write 机制,但支持内存动态分配。)
在Win32 下,WideString 和COM BSTR 类型兼容。Borland 开发工具支持把AnsiString 类型转换为
WideString,但你可能需要明确地使用类型转换。
Working with null-terminated strings(使用零结尾字符串)
许多编程语言,包括C 和C++,它们没有专门的字符串类型。这些语言以及它们创建的系统依赖于零结
尾字符串,它们是0 下标开始的字符数组,并且最后一个是NULL(#0)。因为它们没有长度指示,第
一个NULL 字符就是字符串的结尾。当需要与其它语言创建的系统共享数据时,你可以使用Object Pascal
句法以及SysUtils 单元的特殊例程来处理零结尾字符串。
例如,下面的类型声明可以用于存储零结尾字符串:
type
TIdentifier = array[0..15] of Char;
TFileName = array[0..259] of Char;
Data types, variables and constants
- 53 -
TMemoText = array[0..1023] of WideChar;
当启用扩展语法时({$X+},这是默认的),你可以把一个字符串常量,赋给一个0 下标开始的静态字符
数组(动态数组此时不能工作)。当用字符串常量初始化一个字符数组时,若字符串的长度比数组声明
的长度要短,其余的字符被设置为#0。(注:当用字符串常量给一个字符数组赋值时,结果也总是如此。)
Using pointers, arrays, and string constants(使用指针、数组和字符串常量)
要操作零结尾字符串,要经常需要指针。字符串常量和类型PChar、PWideChar 是赋值兼容的,后两者
表示指针,它们指向一个以0 结尾的Char 或WideChar 字符数组。比如:
var P: PChar;
...
P := 'Hello world!'; (注:编译器在字符串的末尾添加一个NULL)
使P 指向一个内存区域,在这里存储着'Hello world!' ,它的结尾被添加一个NULL 字符,这和下面的效
果相同:
const TempString: array[0..12] of Char = 'Hello world!'#0;
var P: PChar;
...
P := @TempString; (注:和P := TempString 相同)
另外,对于使用PChar 或PWideChar 类型、并采用传值或常量参数的函数,你也可以给它传递字符串常
量,比如StrUpper ('Hello world!')。当给PChar 赋值时,编译器创建一个以0 结尾的字符串的拷贝(generates
a null-terminated copy of the string。注:其实只有一个字符串,PChar 变量是一个指向它的指针),并给函
数传递一个指向这个拷贝的指针。当然,你也可以初始化一个PChar 或PWideChar 类型的常量,比如:
const
Message: PChar = 'Program terminated';
Prompt: PChar = 'Enter values: ';
Digits: array[0..9] of PChar = (
'Zero', 'One', 'Two', 'Three', 'Four',
'Five', 'Six', 'Seven', 'Eight', 'Nine');
0 下标开始的字符数组和PChar 以及PWideChar 兼容。当使用字符数组代替一个指针(值)时,编译
器把数组转换为一个指针常量,它的值对应于数组的第一个元素的地址(也就是数组的地址)。比如
var
MyArray: array[0..32] of Char;
MyPointer: PChar;
begin
MyArray := 'Hello';
MyPointer := MyArray; (注:和@MyArray 相同)
SomeProcedure(MyArray);
SomeProcedure(MyPointer);
end;
上面的代码使用同一个值调用SomeProcedure 两次。
一个字符指针(PChar 或PWideChar)可以像数组一样使用索引。在上面的例子中,MyPointer[0]返回
字符H。索引实际上指定了一个偏移量(对PWideChar 变量,索引自动乘以2)。这样,如果P 是一个字
符指针,P[0]和P^是相同的,它们指的都是数组中的第1 个字符,P[1]是数组中的第2 个字符,依此类
推。P[-1]指的是紧靠P[0]左边的‘字符’(注:这里可以是任何值),编译器对这些索引并不进行边界检
查。
Data types, variables and constants
- 54 -
下面的StrUpper 函数,演示了使用指针索引对一个零结尾字符串进行遍历操作:
function StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;
var
I: Integer;
begin
I := 0;
while (I < MaxLen) and (Source[I] <> #0) do
begin
Dest[I] := UpCase(Source[I]);
Inc(I);
end;
Dest[I] := #0;
Result := Dest;
end;
Mixing Pascal strings and null-terminated strings(混合使用Pascal 字符串和
零结尾字符串)
在表达式和赋值语句中,你可以混合使用长字符串(AnsiString)和零结尾字符串(PChar),并且,对
使用长字符串的函数或过程,你也可以通过PChar 进行传值。赋值语句:S := P(这里,S 是一个字符
串,P 是一个PChar 表达式),把一个零结尾字符串拷贝到长字符串中。(注:长字符串是动态分配内存
的,并在堆中分配,所以,它是把P 指向的字符串复制到自己的内存区。)
在二元操作中,如果一个运算数是长字符串,而另一个是PChar,PChar 将被转换为长字符串类型。(注:
怎么转换呢?应该是复制一个吧。)
你可以把一个PChar 值强制转换为长字符串,当要对两个PChar 进行(长)字符串操作时,这就非常有
用。比如:
S := string(P1) + string(P2);
你也可以把一个长字符串强制转换为零结尾字符串,以下是适用规则:
若S 是一个长串表达式,PChar(S)把S 转换为零结尾字符串,它返回一个指针,这个指针指向
S 中的第1 个字符。
在Windows 下:比如,若Str1 和Str2 是长字符串,你可以这样调用Win32 API 函数MessageBox:
MessageBox(0, PChar(Str1), PChar(Str2), MB_OK);
在Linux 下:比如,若Str 是一个长字符串,你可以这样调用系统函数opendir:
opendir(PChar(Str));
你也能使用Pointer(S)把一个长字符串转换为无类型指针,当S 为空时,转换返回nil。
当把一个长串变量转换为指针时,直到变量被赋一个新值或超出范围,否则指针都将是有效的。
而转换其它长串表达式时,只有在发生转换的语句中,这个指针才是有效的。
当转换一个长串表达式为指针时,通常要把指针作为只读的。只有满足所有以下条件时,你才能
安全地使用指针修改长字符串:
表达式是一个长串变量;
字符串非空;
字符串是唯一的,也就是引用计数为1。要保证字符串是唯一的,调用SetLength、SetString
或者UniqueString 过程。
转换发生后,字符串没有被修改过;
Data types, variables and constants
- 55 -
被修改的字符都在字符串中。请小心不要对指针使用(索引)边界检查。
当混合使用WideString 和PWideChar 时,这些规则同样适用。