导航
  • 全部
...

delphi指针简单入门

hysterical 2003-06-14 03:57:56
delphi指针简单入门:

看一个指针用法的例子:
1 var
2 X, Y: Integer; // X and Y 整数类型
3 P: ^Integer; // P 指向整数类型的指针
4 begin
5 X :=17; // 给 X 赋值
6 P := @X; // 把 x的地址赋给p
7 Y := P^; // 取出p所指向的数值赋给y
8 end;

第二行定义了两个变量X,y. 第三行声明了p是指向整数类型的指针;意味着p能够指向x或者y的地址.第五行赋给x值,第六行把x的地址赋给p.最

后通过p指向的变量赋值给y.此时,x和y有相同的值.

操作符@用来取出变量的地址,也可以取出过程和函数的地址.

而符号^有两个目标,
当它出现在类型定义的前面时如 ^typename 表示指向这种类型的指针;
当它出现在指针变量后边时 如 point^ 返回指针指向的变量的值;

理解指针比较容易理解面向对象的pascal语言,因为指针经常在幕后操作.任何要求动态分配大的内存空间的类型可以用指针类型.例如

,long-string变量,实际在使用指针进行操作.另外一些高级的编程技术需要使用指针类型.
有时指针是适应object pascal严格的类型限制的唯一方法.同过一个通用的指针类型,通过类型转换成不同的指针类型,如下面的例子:
type

PInteger = ^Integer;
var
R: Single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
begin
P := @R; //取出R的内存地址
PI := PInteger(P); //把通用类型转换成指向整数类型的指针
I := PI^;
end;

当然了,实数和整数的存储格式不同.这种赋值是把原始的二进制数据从R拷贝到I,而不进行转换.

保留字nil是一个特殊的常量可以赋给任何指针类型,当nil赋給一个指针时,指针什么也不指向,是一个空指针.

@操作符返回变量的内存中的存储地址,或者是过程\函数\方法;

1.如果变量,@X返回的是x的地址。如果编译选项{$T-}没有打开,着返回的事一个通用的指针,如果编译选项打开了,着返回的是x的类型对应的指

针.

2.如果是例程(过程\函数),@F返回的是F的入口点,@F的类型是一个指针。

3.当@用在类的方法中时,则方法的名称必须有类名,例如@TMyclass.Dosomething
指针指向TMyclass的dosomething方法。


当一个过程变量在赋值语句的左边时,编译器期望一个过程值在赋值语句的右边。这种赋值使得左边的变量可以指向右边定义的过程或者函数

入口点。换句话说,可以通过该变量来引用声明的过程或者函数,可以直接使用参数的引用。

var

F: function(X: Integer): Integer;
I: Integer;
function SomeFunction(X: Integer): Integer;
...
F := SomeFunction; // 给f赋值
I := F(4); // 调用所指向的函数

在赋值语句中,左边变量的类型决定了右边的过程或者方法指针解释。

var

F, G: function: Integer;
I: Integer;
function SomeFunction: Integer;
...
F := SomeFunction; // 给f赋值
G := F; // 把F的值拷贝给G
I := G; // 调用函数

第一句获得函数的入口,第二句将指针复制,第三句获得函数的返回值。

有时候还可以这样使用
if F = MyFunction then ...;
在这里,F的出现导致一个函数调用;编译器调用F指向的函数,然后调用Myfunction,比较结果。这个规则是无论何时一个过程变量(

procedural variable)出现在一个表达式中,它表示调用所指向的函数或者过程。有时F指向一个过程(没有返回值),或者f指向一个需要参

数的函数,则前面的语句会产生一个编译错误。要比较F和Myfunction需要用
if @F = @MyFunction then ...;
@F把F转换成一个包含地址的无类型的指针变量,@myfunction返回myfunction的地址。
获得一个过程变量的内存地址使用@@。例如,@@F返回F的地址。

@操作符通常把一个无类型的指针值赋给一个过程变量,例如:
var StrComp: function(Str1, Str2: PChar): Integer;
...
@StrComp := GetProcAddress(KernelHandle, 'lstrcmpi');
调用GetProcAddres函数,用strcomp指向这个值
任何过程变量可以赋成nil,表示指证什么也不指向。但是试图调用一个nil值的过程变量导致一个错误,为了测试一个过程变量是否可以赋值

,用标准的赋值函数Assigned
if Assigned(OnClick) then OnClick(X);


先到这里吧,我也是一边看帮助一边翻译的,没有参考什么书籍,所以有一些名词可能不太准确,希望大家多多包涵吧,毕竟本人的英文水平有限啊

.呵呵

有什么问题可以参看delphi的帮助的相关内容,个人觉得还是看帮助好一些,而且原文最好,像我这样翻译可能误导大家啊,看的时候要受其精华

弃其糟粕,看完了别骂我就行了,全当我给大家仍块砖头吧,别砸我啊@_@
...全文
给本帖投票
449 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
小宇飞刀 2010-05-29
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hysterical 的回复:]

TO:liuziwei_china(liuziwei)

delphi帮助中的例子:
type
PInteger = ^Integer;
var
R: Single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
begin
P := ……
[/Quote]
这是正解,完全正确!
dbasql 2003-06-26
  • 打赏
  • 举报
回复
学习!!!
feibob 2003-06-20
  • 打赏
  • 举报
回复
强烈建议:DELPHI 5开发人员指南!!!

永远的经典!!
liuziwei_china 2003-06-20
  • 打赏
  • 举报
回复
哈哈,我知道怎么回事了
showmessage(inttostr(INTEGER(p^)));这样就可以了
Northwindrocker 2003-06-17
  • 打赏
  • 举报
回复
学哟!!!!!!!!
liuziwei_china 2003-06-17
  • 打赏
  • 举报
回复
奇怪,我真的不明白,你是怎么测出I的正确结果的,那位兄弟帮测一下

还有纠正你一下关于‘因为这种在不同类型之间的赋值实际是在复制原始的二进制数据。’
其实这些都是指针的相互复制,并不是实际值得转换
zlyanyan 2003-06-16
  • 打赏
  • 举报
回复
不错呀,
hysterical 2003-06-16
  • 打赏
  • 举报
回复
To: zzyx(菜农)、ma369(我是不是很菜) ,呵呵,小弟随便写了几句,不知道是否满意,见笑了,共同进步吧!大家一起讨论讨论很有意思,小弟近来在看COM方面的东东,各位大虾可否站出来指点一二,洗耳恭听!

unit Unit1;

interface

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

type
myclass = class
private
name:string;
procedure showname;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure myclass.showname ;
begin
showmessage('呵呵'+name);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
a:array [1..4] of integer;
i:integer;
p:^integer;
b:array [1..4] of ^integer;
p1:pointer;
my:myclass;
p2:^myclass;
begin
{$O-}
for i:=1 to 4 do
begin
a[i]:=i;
b[i]:=@a[i];
end;
p:=@a;
for i:=1 to 4 do
begin
showmessage(inttostr(p^));
inc(p);
end;

for i:=1 to 4 do
begin
showmessage(inttostr(b[i]^));
end;

my:=myclass.Create ;
my.name:='hello!';
p1:=@my;
showmessage(myclass(p1^).name);
p2:=p1;
p2^.name:='成功了';
p2.showname;
end;

end.
jack968 2003-06-16
  • 打赏
  • 举报
回复
谢谢。我来学习。
ma369 2003-06-16
  • 打赏
  • 举报
回复
学习,
麻烦谈谈关于数组的指针,请教。
dicke 2003-06-16
  • 打赏
  • 举报
回复
收藏
whqcfp 2003-06-16
  • 打赏
  • 举报
回复
我要收藏
zzyx 2003-06-16
  • 打赏
  • 举报
回复
mark,too

问一些弱智问题,请dx们指教。

1.指针能否进行加减的操作?类似c语言中的p+1,p++之类的

如,p为字节指针(该如何定义?)

p指向某个分配的内存(该如何分配,如何释放?)的某个位置

能否加减p的值,使得其指向的内容为其他的?


2.指针指向某个类的的对象实例该如何做,该如何调用该实例的方法?与引用的实例有什么区别?

如,有个类,T,其对象,obj1,obj2,已经创建来
p为T类型的指针
p:^T;
能否用p指向obj1,obj2?
^p=obj1 ?还是^p=@obj1?

这样使用与
t:T;
t=obj1,t=obj2有什么区别

加入T有方法DoSomeThing
那么通过指针,能否调用DoSomeThing?如何调用?

3.在函数间传递指针该注意什么问题


4.指针的优点在哪里?
hysterical 2003-06-16
  • 打赏
  • 举报
回复
TO:liuziwei_china(liuziwei)

delphi帮助中的例子:
type
PInteger = ^Integer;
var
R: Single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
begin
P := @R; //取出R的内存地址
PI := PInteger(P); //把通用类型转换成指向整数类型的指针
I := PI^;
end;

上次我的确做过了测试,发现PI := PInteger(P);这句被优化掉了,我用的是delphi,没有打PACK,后来我加了{$O-}后,确实取出为0(没有给R赋初值),所以说可以返回0。今天我有测试了一下,觉得没有什么问题,你可能没有看清我的帖子中的一句话“实数和整数的存储格式不同.这种赋值是把原始的二进制数据从R拷贝到I,而不进行转换.”,对于你赋值之后的二进制格式我不知道是什么样子,没法描述出来,不过我又做了一下测试,把整形的指针再转换回实数指针取出值后还是原职,所以我觉得并没有问题,因为这种在不同类型之间的赋值实际是在复制原始的二进制数据。

procedure TForm1.Button1Click(Sender: TObject);
type
PInteger = ^Integer;
Psingle =^single;
var
R,t: single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
pi1:psingle;
begin
{$O-}
R := 2;
P := @R; //取出R的内存地址
PI := PInteger(P); //把通用类型转换成指向整数类型的指针
I := PI^;
showmessage(inttostr(I));
p:=pi;
pi1:=Psingle(p);
t:=pi1^;
showmessage(floattostr(t));
end;

在最后的例子中,你可以看到p和pi和t的值是相等的,就是说明指针转换前后的值是相同的,最后t的值和r的值相等,而中间的整数变量p实际是取出的二进制数据。

不知道你是否同意我的观点,我也是刚刚接触指针,有些概念可能还不太正确,希望和你一起讨论。我的邮件:kingsonwei@hotmail.com
crystaltam 2003-06-16
  • 打赏
  • 举报
回复
mark
abcdefg171459 2003-06-15
  • 打赏
  • 举报
回复
up
liuziwei_china 2003-06-15
  • 打赏
  • 举报
回复
真是奇怪了,你真的做了测试么,用的是什么环境

我用的是DELPHI6 PACK2
运行下面程序,得到的就是一个随机数???
注:编译器没有优化掉那一句
procedure TForm1.Button1Click(Sender: TObject);
type
PInteger = ^Integer;
var
R: Single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
begin
R := 2;
P := @R; //取出R的内存地址
PI := PInteger(P); //把通用类型转换成指向整数类型的指针
I := PI^;

showmessage(inttostr(I));
end;
liuziwei_china 2003-06-14
  • 打赏
  • 举报
回复
幸好你在结尾说了一句,不然我就真的砸你了
哈哈,不过可以一起讨论一下

你在这里说
type

PInteger = ^Integer;
var
R: Single;
I: Integer;
P: Pointer; //通用的指针
PI: PInteger;
begin
P := @R; //取出R的内存地址
PI := PInteger(P); //把通用类型转换成指向整数类型的指针
I := PI^;
end;
这段程序由问题,我不知道你试过了没有,反正我试了,是不对的,I的值是一个随机数
不知道是为什么,我正想开个贴子 大家可以讨论一下
nuaabestbo 2003-06-14
  • 打赏
  • 举报
回复
顶!
DelphiBoy2003 2003-06-14
  • 打赏
  • 举报
回复
Delphi指针只需要注意比较严格而已,其他没有什么需要注意的地方啊。
加载更多回复(5)

5,908

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部