zoukankan      html  css  js  c++  java
  • delphi指针

    以下内容分为八部分,分别是
    一、类型指针的定义
    二、无类型指针的定义
    三、指针的解除引用
    四、取地址(指针赋值)
    五、指针运算
    六、动态内存分配
    七、字符数组的运算
    八、函数指针
     

    一、类型指针的定义。

    对于指向特定类型的指针,在C中是这样定义的:
    [cpp] view plain
    1. int *ptr;  
    2.   
    3. char *ptr;  
    与之等价的Object Pascal是如何定义的呢?
    [delphi] view plain
    1. var  
    2.   
    3. ptr : ^Integer;  
    4.   
    5. ptr : ^char;  
    其实也就是符号的差别而已。
     

    二、无类型指针的定义。

    C中有void *类型,也就是可以指向任何类型数据的指针。Object Pascal为其定义了一个专门的类型:Pointer。于是,
    [delphi] view plain
    1. ptr : Pointer;  

    就与C中的
    [cpp] view plain
    1. void *ptr;  
    等价了。

    三、指针的解除引用。

    要解除指针引用(即取出指针所指区域的值),C 的语法是 (*ptr),Object Pascal则是 ptr^。

    四、取地址(指针赋值)。

    取某对象的地址并将其赋值给指针变量,C 的语法是
    [cpp] view plain
    1. ptr = &Object;  
    Object Pascal 则是
    [delphi] view plain
    1. ptr := @Object;  
    也只是符号的差别而已。

    五、指针运算。

    在C中,可以对指针进行移动的运算,如:
    [cpp] view plain
    1. char a[20];  
    2.   
    3. char *ptr=a;  
    4.   
    5. ptr++;  
    6.   
    7. ptr+=2;  
    当执行ptr++;时,编译器会产生让ptr前进sizeof(char)步长的代码,之后,ptr将指向a[1]。ptr+=2;这句使得ptr前进两个sizeof(char)大小的步长。同样,我们来看一下Object Pascal中如何实现:
    [delphi] view plain
    1. var  
    2.   
    3. a : array [1..20] of Char;  
    4.   
    5. ptr : PChar; //PChar 可以看作 ^Char  
    6.   
    7. begin  
    8.   
    9. ptr := @a;  
    10.   
    11. Inc(ptr); // 这句等价于 C 的 ptr++;  
    12.   
    13. Inc(ptr, 2); //这句等价于 C 的 ptr+=2;  
    14.   
    15. end;  
    只是,Pascal中,只允许对有类型的指针进行这样的运算,对于无类型指针是不行的。

    六、动态内存分配。

    C中,使用malloc()库函数分配内存,free()函数释放内存。如这样的代码:
    [cpp] view plain
    1. int *ptr, *ptr2;  
    2.   
    3. int i;  
    4.   
    5. ptr = (int*) malloc(sizeof(int) * 20);  
    6.   
    7. ptr2 = ptr;  
    8.   
    9. for (i=0; i<20; i++){  
    10.   
    11. *ptr = i;  
    12.   
    13. ptr++;  
    14.   
    15. }  
    16.   
    17. free(ptr2);  
    Object Pascal中,动态分配内存的函数是GetMem(),与之对应的释放函数为FreeMem()(传统Pascal中获取内存的函数是New()和 Dispose(),但New()只能获得对象的单个实体的内存大小,无法取得连续的存放多个对象的内存块)。因此,与上面那段C的代码等价的Object
    Pascal的代码为:
    [delphi] view plain
    1. var ptr, ptr2 : ^integer;  
    2.   
    3. i : integer;  
    4.   
    5. begin  
    6.   
    7. GetMem(ptr, sizeof(integer) * 20);  
    8.   
    9. //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);  
    10.   
    11. ptr2 := ptr; //保留原始指针位置  
    12.   
    13. for i := to 19 do  
    14.   
    15. begin  
    16.   
    17. ptr^ := i;  
    18.   
    19. Inc(ptr);  
    20.   
    21. end;  
    22.   
    23. FreeMem(ptr2);  
    24.   
    25. end;  
    对于以上这个例子(无论是C版本的,还是Object
    Pascal版本的),都要注意一个问题,就是分配内存的单位是字节(BYTE),因此在使用GetMem时,其第二个参数如果想当然的写成 20,那么就会出问题了(内存访问越界)。因为GetMem(ptr, 20);实际只分配了20个字节的内存空间,而一个整形的大小是四个字节,那么访问第五个之后的所有元素都是非法的了(对于malloc()的参数同样)。

    七、字符数组的运算。

    C语言中,是没有字符串类型的,因此,字符串都是用字符数组来实现,于是也有一套str打头的库函数以进行字符数组的运算,如以下代码:
    [cpp] view plain
    1. char str[15];  
    2.   
    3. char *pstr;  
    4.   
    5. strcpy(str, "teststr");  
    6.   
    7. strcat(str, "_testok");  
    8.   
    9. pstr = (char*) malloc(sizeof(char) * 15);  
    10.   
    11. strcpy(pstr, str);  
    12.   
    13. printf(pstr);  
    14.   
    15. free(pstr);  
    而在Object
    Pascal中,有了String类型,因此可以很方便的对字符串进行各种运算。但是,有时我们的Pascal代码需要与C的代码交互(比如:用Object Pascal的代码调用C写的DLL或者用Object Pascal写的DLL准备允许用C写客户端的代码)的话,就不能使用String类型了,而必须使用两种语言通用的字符数组。其实,Object Pascal提供了完全相似C的一整套字符数组的运算函数,以上那段代码的Object Pascal版本是这样的:
    [delphi] view plain
    1. var str : array [1..15] of char;  
    2.   
    3. pstr : PChar; //Pchar 也就是 ^Char  
    4.   
    5. begin  
    6.   
    7. StrCopy(@str, 'teststr'); //在C中,数组的名称可以直接作为数组首地址指针来用  
    8.   
    9. //但Pascal不是这样的,因此 str前要加上取地址的运算符  
    10.   
    11. StrCat(@str, '_testok');  
    12.   
    13. GetMem(pstr, sizeof(char) * 15);  
    14.   
    15. StrCopy(pstr, @str);  
    16.   
    17. Write(pstr);  
    18.   
    19. FreeMem(pstr);  
    20.   
    21. end;  

    八、函数指针。

    在动态调用DLL中的函数时,就会用到函数指针。假设用C写的一段代码如下:
    [cpp] view plain
    1. typedef int (*PVFN)(int); //定义函数指针类型  
    2.   
    3. int main()  
    4.   
    5. {  
    6.   
    7. HMODULE hModule = LoadLibrary("test.dll");  
    8.   
    9. PVFN pvfn = NULL;  
    10.   
    11. pvfn = (PVFN) GetProcAddress(hModule, "Function1");  
    12.   
    13. pvfn(2);  
    14.   
    15. FreeLibrary(hModule);  
    16.   
    17. }  
    就我个人感觉来说,C语言中定义函数指针类型的typedef代码的语法有些晦涩,而同样的代码在Object Pascal中却非常易懂:
    [delphi] view plain
    1. type PVFN = Function (para : Integer) : Integer;  
    2.   
    3. var  
    4.   
    5. fn : PVFN;  
    6.   
    7. //也可以直接在此处定义,如:fn : function (para:Integer):Integer;  
    8.   
    9. hm : HMODULE;  
    10.   
    11. begin  
    12.   
    13. hm := LoadLibrary('test.dll');  
    14.   
    15. fn := GetProcAddress(hm, 'Function1');  
    16.   
    17. fn(2);  
    18.   
    19. FreeLibrary(hm);  
    20.   
    21. end;  
  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/pboy/p/5300431.html
Copyright © 2011-2022 走看看