在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
看一个指针用法的例子:
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); =========================================================================
大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是C语言的灵魂,一点都不为过。同时,这种说法也让很多人 产生误解,似乎只有C语言的指针才能算指针。Basic不支持指针,在此不论。其实,Pascal语言本身也是支持指针的。从最初的Pascal发展至今 的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针。
以下内容分为八个部分,分别是 一、类型指针的定义 二、无类型指针的定义 三、指针的解除引用 四、取地址(指针赋值) 五、指针运算 六、动态内存分配 七、字符数组的运算 八、函数指针 一、类型指针的定义。对于指向特定类型的指针,在C中是这样定义的: int *ptr; char *ptr; 与之等价的Object Pascal是如何定义的呢? var ptr : ^Integer; ptr : ^char; 其实也就是符号的差别而已。 二、无类型指针的定义。C中有void *类型,也就是可以指向任何类型数据的指针。Object Pascal为其定义了一个专门的类型:Pointer。于是, ptr : Pointer; 就与C中的 void *ptr; 等价了。 三、指针的解除引用。要解除指针引用(即取出指针所指区域的值),C 的语法是 (*ptr),Object Pascal则是 ptr^。 四、取地址(指针赋值)。取某对象的地址并将其赋值给指针变量,C 的语法是 ptr = &Object; Object Pascal 则是 ptr := @Object; 也只是符号的差别而已。 五、指针运算。在C中,可以对指针进行移动的运算,如: char a[20]; char *ptr=a; ptr++; ptr+=2; 当执行ptr++;时,编译器会产生让ptr前进sizeof(char)步长的代码,之后,ptr将指向a[1]。ptr+=2;这句使得ptr前进两 个sizeof(char)大小的步长。同样,我们来看一下Object Pascal中如何实现: var a : array [1..20] of Char; ptr : PChar; //PChar 可以看作 ^Char begin ptr := @a; Inc(ptr); // 这句等价于 C 的 ptr++; Inc(ptr, 2); //这句等价于 C 的 ptr+=2; end; 六、动态内存分配。C中,使用malloc()库函数分配内存,free()函数释放内存。如这样的代码: int *ptr, *ptr2; int i; ptr = (int*) malloc(sizeof(int) * 20); ptr2 = ptr; for (i=0; i<20; i++){ *ptr = i; ptr++; } free(ptr2); Object Pascal中,动态分配内存的函数是GetMem(),与之对应的释放函数为FreeMem()(传统Pascal中获取内存的函数是New()和 Dispose(),但New()只能获得对象的单个实体的内存大小,无法取得连续的存放多个对象的内存块)。因此,与上面那段C的代码等价的 Object Pascal的代码为: var ptr, ptr2 : ^integer; i : integer; begin GetMem(ptr, sizeof(integer) * 20); //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20); ptr2 := ptr; //保留原始指针位置 for i := 0 to 19 do begin ptr^ := i; Inc(ptr); end; FreeMem(ptr2); end; 对于以上这个例子(无论是C版本的,还是Object Pascal版本的),都要注意一个问题,就是分配内存的单位是字节(BYTE),因此在使用GetMem时,其第二个参数如果想当然的写成 20,那么就会出问题了(内存访问越界)。因为GetMem(ptr, 20);实际只分配了20个字节的内存空间,而一个整形的大小是四个字节,那么访问第五个之后的所有元素都是非法的了(对于malloc()的参数同 样)。 七、字符数组的运算。C语言中,是没有字符串类型的,因此,字符串都是用字符数组来实现,于是也有一套str打头的库函数以进行字符数组的运算,如以下代码: ==============================================================================================
Delphi 中的函数指针
======================================================================
在delphi里利用指针构造链表
2007-08-28 13:41
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论