指针类型的问题(10分)

  • 主题发起人 主题发起人 wjh_wy
  • 开始时间 开始时间
W

wjh_wy

Unregistered / Unconfirmed
GUEST, unregistred user!
不知道有位高手,可以讲解一下指针类型的用法。或者提供下载地址、资料也行呀,
先谢谢各位了!!
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=0620580
 
我没用过指钍,不知道有什么用。?
 
妙兔无花和zw84611推荐的《Pascal 精要》的确是本好书,
http://www.marcocantu.com/EPascal/chinese/default.htm
例子都举到点上,看上一遍(或多遍)包你明白。我看了一遍,解开了很多疑惑。吐血推荐!
 
吐血推荐?我来看看,希望不会失望!
 
浅谈Object Pascal的指针

Nicrosoft(nicrosoft@sunistudio.com) 2001.8.26
(http://www.sunistudio.com/nicrosoft/
东日文档:http://www.sunistudio.com/asp/sunidoc.asp)

大家都认为,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打头的库函数以进行字符数组的运算,如以下代码:
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;
 
to wr960204
谢谢!!不知哪位兄弟可否举这个例了来讲解一下,我是一个菜鸟。或者有关于指针类型
的原码也可以发给我。wjh107@sina.com
 
指针就是数据(广义的数据)在内存中的地址。所以指针和整数类型是兼容的
例如 a:integer;假如a在内存中的存贮地址是$FFFF那么,所有指向a的指针的内容都是$FFFF
例如 b:pinteger;
...
b:=@a;///@是取地址的符号
那么b的内容就是a的在内存中的地址。
可以显示出来
Showmessage(inttostr(integer(b)));
指针的基本含义就是如此。
 
先看看这个

uses WinCRT;

procedure TForm1.Button1Click(Sender: TObject);
var
MyArray: array[0..30] of char;
b: ^char;
i: integer;

begin
StrCopy(MyArray, 'Lloyd is the greatest!')
{get something to point to}
b := @MyArray
{ assign the pointer to the memory location }
for i := StrLen(MyArray) downto 0 do
begin
write(b^)
{ write out the char at the current pointer location. }
inc(b)
{ point to the next byte in memory }
end;
end;

The following code demonstrates that the Inc() and Dec() functions
will increment or decrement accordingly by size of the type the pointer

points to:

var
P1, P2 : ^LongInt;
L : LongInt;
begin
P1 := @L
{ assign both pointers to the same place }
P2 := @L;
Inc(P2)
{ Increment one }

{ Here we get the difference between the offset values of the
two pointers. Since we originally pointed to the same place in
memory, the result will tell us how much of a change occured
when we called Inc(). }

L := Ofs(P2^) - Ofs(P1^)
{ L = 4
i.e. sizeof(longInt) }
end;

 
delphi中有例子
 
你看了VCL源码就会发现

Delphi下的指针,其实就是C中指向指针的指针

呵呵
 
大家好上一年的问题还没有解决望大富翁的高手在新的一年继续帮小弟解决此问题
 
多人接受答案了。
 
后退
顶部