指针是C语言中的一个重要概念及其特点,也是C语言中较难掌握的部分。指针也是内存地址,而指针变量是用来存储内存地址的变量。不同类型的指针变量占用相同长度的内存单元,而存储数据的变量占用的内存空长度因数据类型不同而不同。有了指针,你不仅可以操作数据本身,还可以操作存储数据的变量地址。
引自百度百科
这里提到两个重要的名词:指针和指针变量。其实只要你清楚这两件事,你就会觉得指针并不难(基础使用)。
C之所以强大和免费,在于它灵活的指针应用。所以说指针是C语言的灵魂一点都不为过。
这种说法也让很多人产生误解。似乎只有C语言中的指针才能算是指针。其他语言不支持指针。事实上,Pascal本身就支持指针。从最初的Pascal到现在,Object Pascal在指针的使用上可以说丝毫不逊于C语言的指针。
类型指针
指针的定义。对于指向特定类型的指针,它在C中的定义如下:
int?*ptr;char?*pcr;
等价对象Pascal是怎么定义的?
varptr?:?^Integer;pcr?:?^char;
对于ptr和pcr这样的变量,我们可以称之为指针变量。与普通变量相比,它们的值只是不同而已,类似下图。
无类型指针
无类型指针类似于外国人心目中的上帝。
c有void * type,也就是可以指向任何类型数据的指针。Object Pascal为它定义了一个特殊的类型:指针。所以,ptr:指针;c中带有void * ptr相当于。
实际上指针在新版Delphi中很少使用,所以我个人建议少用甚至不用非类型化指针。
基本用途
就是主指针的解引用和地址,更不用说直接代码演示了。
var??//?定义普通变量,因为是全局变量可以直接赋初始值??Age:?Integer?=?10;??//?定义同类型的指针变量,可以使用^数据类型的形式,他们是等同的??PAge:?PInteger;begin??//?给指针变量赋值,它只能接收这样的值??PAge?:=?@Age;??//?获取指针变量PAge的值,即变量Age的内存地址??Writeln(IntToHex(Integer(PAge)));??//?直接获取变量Age的内存地址??Writeln(IntToHex(Integer(@Age)));??//?获取指针变量中存储的具体值(解除指针引用)??Writeln(PAge^);??readln;end.
上面的代码只演示了一级指针,指针是可以嵌套的。
指针操作
在C中,你可以移动指针,例如:
char?a可能我接触Delphi的时间比较短,几乎没有把指针操作作为知识点。;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?可以看作?^Charbegin???ptr?:=?@a;???Inc(ptr);?//?这句等价于?C?的?ptr++;???Inc(ptr,?2);?//这句等价于?C?的?ptr+=2;end;
[20]
字符数组的操作
在C #中,没有字符串类型。所以字符串都是用字符数组实现的,所以也有一套以str开头的库函数来计算字符数组。
char?str[15];char?*pstr;strcpy(str,?"teststr");strcat(str,?"_testok");pstr?=?(char*)?***lloc(sizeof(char)?*?15);strcpy(pstr,?str);printf(pstr);free(pstr);
但是,在Object Pascal中,使用字符串类型,可以方便地对字符串执行各种操作。但是,有时候当我们的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?也就是?^Charbegin???StrCopy(@str,?'teststr');?//在C中,数组的名称可以直接作为数组首地址指针来用????//但Pascal不是这样的,因此?str前要加上取地址的运算符???StrCat(@str,?'_testok');???GetMem(pstr,?sizeof(char)?*?15);???StrCopy(pstr,?@str);???Write(pstr);???FreeMem(pstr);end;
函数指针
函数指针可以用于两个不同的目的:声明函数指针类型的变量;或者将函数指针作为参数传递给另一个例程。
Delphi可以通过函数指针将一个函数作为参数传递,然后在另一个函数中调用它。首先,声明函数指针类型TFunctionParameter。
type??????????TFunctionParameter?=?function(const?value?:?integer)?:?string;?//函数指针
定义一个作为参数传递的函数。
function?One(const?value?:?integer)?:?string;????????????????????????????//函数-实例1begin??result?:=?IntToStr(value)?;end;function?Two(const?value?:?integer)?:?string;????????????????????????????//函数-实例2begin??result?:=?IntToStr(2?*?value)?;end;
定义将使用动态函数指针参数的函数。
function?DynamicFunction(f?:?TFunctionParameter;?const?value?:?integer)?:?string;begin??result?:=?f(value)?;end;
上述动态函数的使用示例
var??s?:?string;begin??s?:=?DynamicFunction(One,2006)?;??ShowMessage(s)?;?//will?display?"2006"??s?:=?DynamicFunction(Two,2006)?;??ShowMessage(s)?;?//?will?display?"4012"end;
虽然这种调用方式比直接调用更麻烦,但是我们为什么要用这种方式呢?
因为在某些情况下,调用什么样的函数需要在实际中(运行时)决定,你可以根据条件来判断,实现用同一个表达,调用不同的函数,很是灵活.利用函数指针我们可以实现委托,委托在.NEt中被发挥得淋漓尽致,但Delphi同样能实现实现回调机制
例子
//********************************************************//?函数指针(指向一般函数和过程)//*********************************************************unit?DelegateUnit;inte***ce?????procedure?Func1;?????//定义两个函数型构相同但功能不同的函数????function????FuncAdd(VarA?,?VarB?:?Integer):Integer;????function????FuncSub(VarA?,?VarB?:?Integer):Integer;type????DelegateFunc1?=?procedure;????DelegateFuncCalc?=?function(VarA?,?VarB?:?Integer):Integer;var??I?:?Integer;implementationprocedure?Func1;begin??????Writeln('Func1?was?called!');end;function????FuncAdd(VarA?,?VarB?:?Integer):Integer;begin?????Result?:=?VarA?+?VarB;end;function????FuncSub(VarA?,?VarB?:?Integer):Integer;begin???Result?:=?VarA?-?VarB;end;end.
转移
program?Delegate;{$APPTYPE?CONSOLE}uses??DelegateUnit;?var????ADelegateFunc1?:?DelegateFunc1;????ADelegateFuncCalc?:?DelegateFuncCalc;?begin?????//通过函数指针调用过程?????ADelegateFunc1??:=?Func1;?????ADelegateFunc1?;????//通过同种方式调用不同函数????ADelegateFuncCalc??:=?FuncAdd;????Writeln(ADelegateFuncCalc(3,5));????ADelegateFuncCalc??:=?FuncSub;????Writeln(ADelegateFuncCalc(3,5));end.
本文来自枯萎○还行投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/595583.html