关于PChar和指针

  对于刚开始学编程的人来说,指针无疑是最大的恐惧和进步障碍了. 我本人也是如此,居然毕业1年后还是见到^就怕的要命.其实现在想来,其实指针变不是什么难的东西,而且灵活运用它能有带来许多便利,很多人把指针比喻成门牌号码,这个比喻是再恰当不过了,一个门牌号码你当然看不到,这个门牌所对应的具体的是哪个房子哪栋楼是什么样的吧,指针也一样,在win32里它也只是一个占4个字节(32位)的数字,而这个数字对应的内存具体所保存的是什么东西,你不去访问它是不知道的.

  很多人在写要提供其他语言调用的dll的时候,知道要用pchar来做为字符串,我就以pchar来做一些简单的介绍吧.

首先我们来看一下pchar的定义:在随便哪个事件里定义一个P:PChar将鼠标放到PChar上,可以看到type System.PChar=^Char可以看到PChar就是一个指向Char类型的指针,另外PAnsiChar类型的也可以看到type System.PAnsiChar:PChar 所以你应该以后不会问PAnsiChar和PChar有什么不同了吧.

既然是指针,如果要使用就要给它分配内存,或者将它指向一个已经分配了的内存.我们先来看给PChar分配内存的函数,delphi提供了一个叫StrAlloc的函数来给null-terminated string类型的字符串分配内存,该函数可以用来给PChar分配size(参数)字节的内存,并将PChar指向第一个字符.知道它的作用,我们再来看下它的源代码(按住Ctrl点函数):

function StrAlloc(Size: Cardinal): PChar;
begin
  Inc(Size, SizeOf(Cardinal));
  GetMem(Result, Size);
  Cardinal(Pointer(Result)^) := Size;
  Inc(Result, SizeOf(Cardinal));
end;

一句来解释下,Inc(Size, SizeOf(Cardinal));将要分配的内存加上一个Cardinal的长度,为什么后面再说

GetMem(Result, Size);分配size长度的内存,并将Result指向这块内存开头,注意GetMem分配的都是堆内存.

Cardinal(Pointer(Result)^) := Size;将Result指向的内存的前4个字节填上Size的大小.

Inc(Result, SizeOf(Cardinal));将Result的指加4,也就是将Result往后指了4个字节
现在可以看出来了吧,StrAlloc分配内存时会用4个字节来保存函数申请的内存的大小.对应的释放的函数StrDispose函数这里就不说了.所以如果要得到一个PChar的申请的缓存的大小只要看这4个字节就知道了.其实只要取到这4个字节保存的数据-去4就是了,但其实delphi里提供了StrBufSize函数可以获取,方法就是这样的,大家可以注意到它另外申请了个PChar变量,大家可以自己想想如果不用这个变量的话程序该怎么改,还有函数的定义该怎么改.

来看这样一段程序:

var
  P:PChar;
  S:String;
begin
  S:='aaaa';
  try
    P:=StrAlloc(1024);
    //P:=StrPCopy(P,S);
    P:=PChar(S);
    Showmessage(P);
    Showmessage(InttoStr(Length(P)));
  finally
    StrDispose(P);
  end;
end;

以上代码运行会发现StrDispose(P);这句会报Invalid pointer operation,非法的指针操作,为什么呢?

因为P:=PChar(S);这句已经将P指向一个局部变量的内存,而它的分配和释放是由delphi编译器来管理的,你无法操作的,而你原来申请的1024个字节的内存已经泄露了.所以指针操作里千万不要再创建内存后又重新指向另外一个地方.前2天有个人问我,2个PChar的字符能不能连接直接用+来,也许你该想想,2个门牌号码的数字加起来是不是就是代表这2个房间呢? 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值