Delphi指针详解

Delphi指针详解2007-12-04 06:08:57|  分类: DLL学习 阅读91 评论0   字号:大中小 订阅
大家都认为,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。于是, 字串7
   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打头的库函数以进行字符数组的运算,如以下代码:
   char str[15];
   char *pstr;
   strcpy(str, "teststr");
   strcat(str, "_testok");
   pstr = (char*) malloc(sizeof(char) * 15);
   strcpy(pstr, str);
   printf(pstr);
   free(pstr);
   而在Object Pascal中,有了String类型,因此可以很方便的对字符串进行各种运算。但是,有时我们的Pascal代码需要与C的代码交互(比如:用 Object Pascal的代码调用C写的DLL或者用Object Pascal写的DLL准备允许用C写客户端的代码)的话,就不能使用String类型了,而必须使用两种语言通用的字符数组。其实,Object Pascal提供了完全相似C的一整套字符数组的运算函数,以上那段代码的Object Pascal版本是这样的:
   var str : array [1..15] of char;
     pstr : PChar; //Pchar 也就是 ^Char
   begin
     StrCopy(@str, ‘teststr‘); //在C中,数组的名称可以直接作为数组首地址指针来用
     //但Pascal不是这样的,因此 str前要加上取地址的运算符
     StrCat(@str, ‘_testok‘);
     GetMem(pstr, sizeof(char) * 15);
     StrCopy(pstr, @str);
     Write(pstr);
     FreeMem(pstr);
   end;
  
  八、函数指针。在动态调用DLL中的函数时,就会用到函数指针。假设用C写的一段代码如下:
   typedef int (*PVFN)(int); //定义函数指针类型
   int main()
   {
     HMODULE hModule = LoadLibrary("test.dll");
     PVFN pvfn = NULL;
     pvfn = (PVFN) GetProcAddress(hModule, "Function1");
     pvfn(2);
     FreeLibrary(hModule);
   }
  就我个人感觉来说,C语言中定义函数指针类型的typedef代码的语法有些晦涩,而同样的代码在Object Pascal中却非常易懂:
   type PVFN = Function (para : Integer) : Integer;
   var
     fn : PVFN;
     //也可以直接在此处定义,如:fn : function (para:Integer):Integer;
     hm : HMODULE;
   begin
     hm := LoadLibrary(‘test.dll‘);
     fn := GetProcAddress(hm, ‘Function1‘);
     fn(2);
     FreeLibrary(hm);
   end;

时间: 2024-09-29 09:06:18

Delphi指针详解的相关文章

C++Study 指针详解

C++指针详解 指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区.让我们分别说明. 先声明几个指针放着做例子: 例一: int *ptr; char *ptr; int **ptr; int (*ptr)[3]; int *(*ptr)[4]; 指针的类型 从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类

[转]C++ 智能指针详解

C++ 智能指针详解   一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见. 用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法.包括:std::auto_ptr.boost::scoped_ptr.boost::shared_ptr.boost::scoped_array.boost::shared

C++函数指针详解

学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很蛋疼的难点,那就是函数指针了.本博文详细介绍一下常见的各种坑爹的函数指针. 至于指针的详细学习,推荐这篇博文C++指针详解 与数据一样,函数也有地址,函数的地址就是内存中存放函数语言代码的起始地址.函数指针就是指向这个地址.函数指针所指向的类型,就是函数本身.我们知道,指针所指向类型代表了指针所指向的内存区域的大小.所以函数指针所指向的类型,就是函数在内存中所占据内存的大小.知道了函数的起始地址和大小,所以函数指针可以很轻易的代替函数

Java指针详解___案例解答

大家先看看下面的这个程序:--------->相信初级程序员就能看得懂 int k1=1; int k2=k1; k2+=8; System.out.println("k1:"+k1); 大声回答,k1等于几? 输出: k1:1 这是为什么呢?不是明明k2已经指向了k1,然后k2的值发生改变,k1就要发生改变吗? 刚开始:k1 ,k2指向同一个内存地址: 当发生语句:k2+=8的时候,我们这么看:k2=k2+8,第一步:k2+8,很简单啊,等于9呗,这时候,内存空间会自动分配一个

C++ 智能指针详解

一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见. 用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法.包括:std::auto_ptr.boost::scoped_ptr.boost::shared_ptr.boost::scoped_array.boost::shared_array.boost:

【C++】智能指针详解(一):智能指针的引入

智能指针是C++中一种利用RAII机制(后面解释),通过对象来管理指针的一种方式. 在C++中,动态开辟的内存需要我们自己去维护,在出函数作用域或程序异常退出之前,我们必须手动释放掉它,否则的话就会引起内存泄漏. 例如:我们用指针变量来创建对象时,需要手动来删除它 string * pstr = new string("hello world!"); .... delete pstr; 事实上,即使我们非常谨慎,但有时候的一些情况仍然会让我们防不胜防: //情况一:在程序某个分支内,忘

彻底搞定C语言指针详解

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: 内存地址→ 6 7 8 9 10 11 12 13 ----------------------------------------------------------------- ... | | | | | | | |.. ------------------------------- ---------------------------

指针数组,数组指针,指针函数,函数指针,二级指针详解

先看个简单的:char *p,这定义了一个指针,指针指向的数据类型是字符型,char  *(p)定义了一个指针P: char *p[4], 为指针数组,由于[]的优先级高于*,所以p先和[]结合,p[]是一个数组,暂时把p[]看成是q,也就是char *(q),定义了一个指针q,只不过q是一个数组罢了,故定义了一个数组,数组里面的数据是char *的,所以数组里面的数据为指针类型.所以char *p[4]是四个指针,这四个指针组成了一个数组,称为指针数组,既有多个指针组成的数组. char(*p

Delphi 关键字详解

absolute//它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同. var   Str: string[32];   StrLen: Byte absolute Str; //这个声明指定了变量StrLen起始地址与Str相同. //由于字符串的第0个位置保存了字符串的长度, 所以StrLen的值即字符串长度. begin   Str := 'abc';   Edit1.Text := IntToStr(StrLen); end; abstract//它允许你创建抽象的方法