在Pascal语言下实现动态数组和大数组的讨论(一)

在Pascal语言下实现动态数组和大数组的讨论
关键:指针的操作

Tips : 关于强制类型转换
       有的时候,Pascal语言提供的强制类型转换的功能不是那么好用,
       因为有的类型无法强制类型转换,至少编译器这么认为。
       这里提供一个强制类型转换的方法,虽然说不是万能的,
       但是要比原先编译器提供的功能要强多了。
       使用(@F)^的方法可以让Turbo Pascal语言的编译器忽略F的类型,
       所以你可以把F强制转换为任意的类型,这里需要注意的是,
       (@X)^结构和正常强制类型转换的区别,例如:
       longint(bytevar)取得的是和bytevar相同的值,
       而longint((@bytevar)^)取得的值是和Bytevar公用绝对地址的LongInt值
       (也就是说,一个longint读取的4个字节的值),换言之,
       就是longint(bytevar)是数值的转换,而longint((@bytevar)^)是地址的操作。

当然,这里说的主要问题和这个没有太大的关系,
首先,我们说一下动态数组实现。
有这样的一个程序,
Program Test(Input, Output);
Type IntArray = Array[1..1] Of Integer;
Const ElemCount = 20;
Var
A : IntArray;
P : ^Integer Absolute A;
i : Integer;
Begin
GetMem(P, ElemCount * SizeOf(Integer));
For i := 1 to 20 do
    Begin
    A[i] := i;
    Writeln(A[i]);
    End;
FreeMem(P, ElemCount * SizeOf(Integer));
End.
这个程序是最初的想法,就是让指针和数组公用同一个地址空间,
以便于访问指针的第二个元素。但是,很不幸,这个想法是错误的。
抛出循环的部分不说,就是FreeMem的操作就导致了一个错误,
因为数组的空间不能被释放。

于是,笔者想到了使用基本的汇编级别操作来访问指针所指向的空间,
当然,要以高级语言的形式来实现。
找到了几个比较实用的函数:
Seg(Var V); {获得变量V的段地址}
Ofs(Var V); {获得变量V的偏移地址}
Move(Var Src, Dest; Count : Word);
    {调用汇编指令MOVSB,把Word个字节的数据从Src移动到Dest,
    不做任何的范围检测,所以要注意安全性}
Ptr(Segment : Word, Offset : Word);
    {根据给定的段地址Segment和偏移地址Off}
对于Seg和Ofs,这两个函数需要注意的是,函数的参数是变量V,而不是指针V,
虽然变量和指针的本质问题都反映在内存的地址上,但是,例如:
我要获得指针p所记录的的段地址和偏移地址。

Tips :Pascal语言中的指针是具有4个字节空间的类型,
       用于描述该指针的段地址和偏移地址。
       而Seg函数和Ofs函数返回的都是Word(2字节)类型的数据。

Var p:^integer;
Begin
new(p);
Writeln(Seg(p)); Writeln(Ofs(p));
dispose(p);
End.

如果像上述代码那么写就错了,上面的程序获得的是指向p的指针的值,
而不是p的值。

正确的写法应该为

Var p:^Integer;
Begin
new(p);
Writeln(Seg(p^)); Writeln(Ofs(p^));
dispose(p);
End.

至于为什么,我举这个例子只是说明Seg和Ofs参数的理解,而P和P^的区别,
回去问你的计算机老师,如果你没有计算机老师的话,看看Pascal的基本教材,
就可以知道了。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值