PASCAL的指针操作(150分)

  • 主题发起人 主题发起人 zcy
  • 开始时间 开始时间
Z

zcy

Unregistered / Unconfirmed
GUEST, unregistred user!
在C语言中,可以直接申请一块内存,然后可以用指向一个地址的指针依次遍历这块内存,
如: *i=(int *)malloc(sizeof(int)*10),一次可以申请10个字节的内存,然后直接用i
进行地址的加减即可完成对这块内存的访问,在PASCAL中有无这样的方法,
 
var
i:array[10] of byte;
 
基本上可以,但是麻烦多了。
指针不是pascal 的强项。最好少用。
 
少用指针!
少惹麻烦!
 
var i :array of integer;

SetLength(i,10);
 
最好不用指针.
 
var
i: ^Integer;
begin
GetMem(i, SizeOf(Integer) * 10);
......
FreeMem(i);
end;
 
Delphi中指针功能非常强大,所有c中能实现的指针Delphi中都能实现. 上面认为Delphi
指针不是强项的只是一种误解(或者对指针的机制一知半解).
由于Pascal语言的限制, 用Delphi的指针时很多情况下需要强制类型转换. Delphi中
提供了很多指针类型, 而且非常方便的是你可以自定义自己的指针类型.
一个经验: 要掌握一种数据类型并且能够灵活应用,一个比较好的办法是别考虑什么
类型是什么名字, 而只需要考虑这种类型的变量将占用多少字节. 凡是字节数相同
的类型都可以认为是同一类型 :-), 提供不同类型只是为了编译器能够更方便的查找
错误而已. 比如: Integer, Pointer, PChar, TSmallPoint甚至 array [0..4] of Char
你都可以把他们当成是同一类型加以使用(有了这种思路, 可以实现很大的程序灵活性
和代码高效性). 所以我很不理解的是JAVA中不支持指针(因此我也认为用JAVA绝对
不可能写出很高效的程序, 而且会有很多C/C++/DELPHI中用一句话可以完成的工作
在JAVA中需要用一个复杂过程, 消耗很多额外内存才能达到相同目的).
就事论事, 根据你的问题在Delphi中和C中的解决方案没什么两样.
var
a: Pointer
// 或者任何其他指针类型
begin
GetMem(a, 10)
// 分配10字节
PInteger(a)^ := Integer(Form1)
// 将form1(其实Delphi中所有的类都可以认为是指针)
// 保存到a[0..3]中
// 这里是和C的区别, Delphi中需要进行指针类型转换,
// 主要是为了"欺骗"编译器, 免得程序无法编译通过.
(PChar(a)+SizeOf(Integer))^ := 'B'
// a[4]中保存一个字符'B'
....
end;
 
DELPHI的指针功能的确不输于C,DELPHI里的大多东西都是指针!
同志们,象另一只眼学习!!!!!
 
to:Another_eYes
呵呵,这么说,一定是对java太不了解了, 不理解java 抛弃指针的用意和原因。
pascal 和 c的指针的看法我同样不能苟同,
灵活的指针是c的特点,因为它是若类型检查的,这是pascal 不能比拟的,
这并不是说不能实现,而是说不方便,
如果你了解编译,你会发现他们编译出来的代码的天壤之别。

多了我也不说了。
 
不好意思, 我是从汇编开始学电脑的. 所以我对所谓指针的理解是其实它和一个Integer
没有两样. 我不相信编译器能把它变得面目全非. 顺便说一句, 在Delphi中我使用指针
一般把它转换成Integer再进行偏移量操作然后再转回指针去取具体地址的内容. 我不
相信Delphi能多 加什么代码在里面(指针与整型之间的强制转换只是给编译器用的, 并
不会在目标程序中生成额外代码, 我不相信具备这么多年编译器设计经验的Borland会
不知道这个道理)
也许受汇编影响太深. 指针在我心目中一直和整型没区别. 而且我在编程序中不会太
遵守所谓的类型, 一切以使用方便为目的(我就常使TPoint和Double合用一个变量, 尤
其在数组中用处很大). 我承认, 我编程序不很遵守结构化编程的要求. 不过我也相信,
有经验的程序员一定也和我一样会出现一个变量用于保存多种类型的数据的情况.
而且我相信, 所有编译器都不会对这种使用生成什么额外代码.
 
C的编译代码比较接近汇编语言,Pascal的编译速度较快,
但是代码的编译没有C语言那么的接近汇编。
同意Another_eYes的大体上的说法。
 
同意Another_eYes的说法。
puzzle说的编译方法,我没仔细看,可以用DelphiIDE的CPU Watch看一下就知道了。
在Pascal中,指针很好用;至少在DOS时代是这样。
另外,Another_eYes说的Integer与指针的关系中少了一点,就是两者的值域可能
不同,只是使用中几乎不会有问题。
关于Java,我没用过;仅仅知道它是全对象的编程。也许因为这点,它原则上不允许
使用指针,只在解释器内部使用吧。
 
大家说得很好,可是只有理论,能否举个例子来说。
再帮忙看一下下面这段代码,
var
hMemHandel : Integer;
p,MemPoint : Pointer;
ad : LongInt

begin
hMemHandle := CreateFileMapping ($FFFFFFFF,nil,PAGE_READWRITE,
0,100,'MYMEMORY')

if hMemHandle <> 0 then
MemPointer:=MapViewOfFile (hMemHandle,FILE_MAP_ALL_ACCESS,0,0,0);
我申请了一块内存,我想在这块内存中依次存放几个数值(暂且当它们全是整型)
如果只存一个值,可以用Integer(MemPointer^):=100来实现,而且值也可以读出,
但现在我想在下面紧跟着再存一个INTEGER值,我现在用如下方法:
用Addr取得MemPointer的地址,再把这个地址加上SIZEOF(Integer),再用
Ptr函数取得指向这个地址的指针,再对这个指针赋值,我想这样从理论上来说,
应该是对的,可就是读出来不对。我在跟踪时,发现在运行中转换得到的地址
与MemPointer的地址相去甚远。
ad:=Integer(addr(MemPointer))
ad:=ad+sizeof(Integer)
p:=Ptr(ad)

请诸位大侠指教。
另外,我想最好不要用数组来做,因为我要存的数值不会是同一类型的,可能有整型,
也可能有浮点型(如果全是同一类型,我可以申请一个数组,再把它们一次拷入指定内存
中。这已实现。)。
 
呵呵, 看来你还是没有理解什么是指针. 请将MemPointer理解成一个整数.
MemPointer中保存的值是另一块内存的首地址. 那块内存中保存的是你具体想保存的
内容(比如一个具体的字符串).
知道你的问题了吗? Addr(MemPointer)取到的是MemPointer这个变量存放的地址.
根据你var部分的定义, 我们可以知道:
Addr(MemPointer) + SizeOf(Integer)将得到ad这个变量的地址.
你 用MemPointer变量中的<font color='red'>值</font>(指向另一块内存的地址) 和ad这个变量的<font color='red'>地址</font>来比较,
当然相去甚远了.

举一个例子来说明:
假设一个邮局, 其中有很多放信的邮箱. 这些邮箱按顺序排放.
第一个邮箱的名字叫hMemHandel
第二个邮箱的名字叫p
第三个邮箱叫MemPointer
第四个邮箱叫ad
现在MemPointer这个邮箱中放了一封信, 信上的地址是某个街道的具体门牌号, 假设
是xx街500号.
你的目的是想访问这个门牌号的下一个门牌(501号).
看看你怎么做的呢?
addr(MemPointer)取得邮箱的顺序号: 这里将得到3
将它加1=4写成一封信放如ad邮箱里 ad := .....;
再将这封信的内容复制到p邮箱: P := Ptr(ad);
当然: p里面的内容("第4号邮箱")和MemPointer里面的内容("xx街500号")相差甚远,
而不是只差一个门牌号
 
注意:一个是MemPointer指向的内存单元,一个是指向保存MemPointer的内存单元!
 
Another_eYes说得很对,我昨天犯了一个常识性的错误。今天早上我才反应过来,
正像Another_eYes所说的那样,其实根本不需要什么ADDR,因为MemPointer本身就是内存
的地址,只要直接用INTEGER(MemPointer)就可以得到了,再对它进行加减就可以了,
谢谢大家,谢谢Another_eYes。至于分数嘛,Another_eYes(123)剩下27分,大家
见者有份,每人三分,如何?
 
我也有份吗
俺一直 关注着呢
(嘿嘿 片分的)
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
730
SUNSTONE的Delphi笔记
S
S
回复
0
查看
738
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部