DELPHI中的指针类型的常规信息
一个指针变量指示了内存的位置,PASCAL通用指针类型的名称是Pointer。Pointer。有时又被称为无类型指针,因为它只指向内存地址,但编译器并不管指针所指向的数据,这一点与PASCAL严谨的风格似乎不相称,所以建议你在大部分情况下用有类型的指针。
有类型指针在你的应用程序的Type部分用^ (或Pointer)运算符声明。对于有类型指针来说,编译器能准确地跟踪指针所指内容的数据类型,这样用指针变量,编译器就能跟踪正在进行的工作。以下是声明指针的例子。 要记住一个指针变量仅仅是存储一个内存的地址,为指针所指向的内容分配空间是程序员要干的工作,用在前面介绍过的并列在表2 - 6中的内存分配例程来分配内存。
注意如果一个指针没有指向任何数据,它的值是n i l,它就被称为是零( n i l )指针或空(null) 指针。
要访问一个指针所指向的内容,在指针变量名字的后面跟上^运算符。这种方法称为对指针取内容。下面的代码演示怎样用指针:
用New()函数能为一个指针分配指定长度的内存空间。在为某结构分配内存时,因为编译器知道要分配的内存的大小,所以调用New()就能分配到所需的字节,而且它比GetMem或Allocmem()更安全,更易于使用。但不能用New()为Pointer 或Pchar变量分配内存,因为编译器不知道需要分配多大的内存。另外要记住用Dispose()函数来释放用New()分配的内存。当编译器不知道要分配多少内存时,就要用到GetMem和Allocmem(),在对PChar和Pointer类型分配内存时,编译器不可能提前告诉你要分配多少,因为它们有长度可变特性。要注意,不要试图操作分配空间以外的数据,因为这是导致“Access Violation”错误最常见的原因。用FreeMem()来释放由GetMem( )和Allocmem( )分配的内存。顺便说一下,Allocmem要比GetMem()安全,因为AllocMem()总是把分配给它的内存初始化为零。
C程序员在学习Object Pascal时感到头痛的是, Object Pascal对指针类型的检查非常严格,例如,
下面的代码中变量a和变量b并不兼容:
var
a :^integer;
b :^integer;
相反,在C语言中它们是兼容的:
Object Pascal认为每一个指针类型是相异的,为了把a的值赋给b,你必须建立一个新的类型,示例如下:
type
Pin = ^integer;
var
a,b :pin;
也可以直接写
var
a,b : ^integer;
在使用指针的过程中我遇到的一个问题
上述部分都是在DELPHI中使用指针的常规操作,你在很多地方,都可以看到类似的文字。下面我想记录一个在使用指针过程中,我遇到的问题,这也是为我为什么今天要写此文的目的。
通常,我们对指针所指向数据的操作都会用这样的方式进行,pp^.name := '';或者a^ := 1;注意我们使用到了【^】这个符号,但在DELPHI7以及TURBO DELPHI中,我发现,对于指向符合结构的指针,例如上面的pp所指向的Tinfo(记录),你可以不使用^,对于指向integer这种类型的指针,则必须使用^,现在我只能从字面上来理解这种区别,至于究竟为什么,没想明白。但在我的测试程序中可以正常使用,甚至我在DELPHI的DEMO程序中也发现这样的使用,这至少证明这样用没问题,但不知道为什么,希望知道的人可以告诉我,直接留言或者发e_mail给我(wudi_1982@hotmail.com)。
下面是我用来测试的例子
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
Tinfo = record
name : string[10];
ff : integer;
end;
pinfo = ^Tinfo;
pint = ^integer;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
...{ Private declarations }
public
ary : array[0..1] of tinfo;
p : pinfo;
aryi : array[0..1] of integer;
end;
var
Form1: TForm1;
implementation
...{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
p.name := '1234'; //这里我并没有使用^
showmessage(p.name+inttostr(p.ff));
inc(p);
p^.name := '6789';
showmessage(p^.name+inttostr(p^.ff));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
pp : pint;
begin
pp := @aryi;
showmessage(inttostr(pp^));
inc(pp);
showmessage(inttostr(pp^));
// inc(pp);
// showmessage(inttostr(pp));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
aryi[0] := 100;
aryi[1] := 200;
with ary[0] do
begin
name := 'wudi';
ff := 1;
end;
with ary[1] do
begin
name := 'zhangqian';
ff := 2;
end;
p := @ary;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
test : pinfo;
begin
new(test);
test.name := 'abc';
test.ff := 10;
ShowMessage(test.name+inttostr(test^.ff));
Dispose(test);
end;
end.
Tinfo = record
name : string[10];
ff : integer;
end;
pinfo = ^Tinfo;//一个指向Tinfo结构的指针
pint = ^integer;//一个指向整形指针
var
P:Pointer; // 一个无类型的指针
P2:pinfo ; // PFoo的实例
Tinfo = record
name : string[10];
ff : integer;
end;
pinfo = ^Tinfo;
var
pp : pinfo
begin
new(pp);
pp^.name := 'wudi';
pp^.ff := abc;
dispose(pp);
end;