你的第一段代码可以执行通过吗?代码在我的系统中运行不能通过的:
  new(pt);  sp(pt)^:='abc123';
  showmessage(sp(pt)^);  dispose(pt);上面的代码应该是不能运行通过的,因为只是new了一下,并没有分配空间。
将代码修改为:
  new(sp(pt));  sp(pt)^:='abc123';
  showmessage(sp(pt)^);  dispose(pt);就可以了,这样编译系统就知道你要new一个^string类型的指针。

解决方案 »

  1.   

    简直就是在胡搞。
    string本身就是指针类型。
    Pointer是无类型指针,无类型指针,没有类型,new自然不可能知道该给其分配多大的内存空间。
    此外,上面的赋值语句指针一律都没有分配内存,就直接使用,这是大忌。(我唯一不能确定的是string,Delphi确实可以为string自动分配内存,但是用^string,我就不清楚了,而且这样,纯粹是画蛇添足)
      

  2.   

    to chechy:我看过你的言论,我深感荣幸地得到你的关注,说我胡搞,对我而言,真是太舒服了呀!太谢谢你的关心了。
    不过,我是这样地感到奇怪的?我以上的两种情况为什么结果不一样?为什么一种可以得到正确的结果,而另一种则会在执行过程中出错的。是与string本身是一个指针类型有关吗?string类型的变量本身是一个指针,当然要用上四字节来表示内存地址的。那所谓字符串的引用计数放在哪里?(真正的菜鸟问题!)
    对于你的:“Pointer是无类型指针,无类型指针,没有类型,new自然不可能知道该给其分配多大的内存空间。”
    给程序加上这样的一句: showmessage(inttostr(sizeof(pt^)));
    可以发现,原来pointer类型的变量己经分配了4字节的内存!对于你的:“此外,上面的赋值语句指针一律都没有分配内存,就直接使用,这是大忌。”
    这个,以上过程不是没有分配内存的,只不过,进行了指针的转化而己。
    而且,如果把我以上的两个过程的一个,分开两个来执行,如下所示,则并不会出错的。
    再加上我的注释,看看是不是有问题的!
    type sp=^string;
    var  pt:^pointer;
    begin
      new(pt);//pt是一个指向pointer的指针!建立一个pointer的变量并把地址给pt!
      sp(pt)^:='abc123';//sp(pt)的作用是把pt转化成指向字符串的指针!
    //这样,sp(pt)^就变成了一个字符串变量,可以赋值给它!
      showmessage(sp(pt)^);//显示出来!
      dispose(pt);
    end;
    另一个:
    type ip=^integer;  
    var  pt:^pointer;
    begin
      new(pt);//pt是一个指向pointer类型的指针
      ip(pt)^:=1234;//把pt转化成ip类型的数据,即整数类型的指针!
    //这样,ip(pt)^就变成了一个整数变量,给它赋值1234.
      showmessage(inttostr(ip(pt)^));//显示出来!
      dispose(pt);
    end;
      

  3.   

    这个chechy,到哪去了?怎么不见踪影?我在等你的答案呢!
      

  4.   

    还等在过两天,我在重装机器,都快被这台AMD搞定了。
      

  5.   

    chechy要不要我给你发邮件的啊?
      

  6.   

    好吧,我现在给你解释。不过我不会对某些术语进行解释,如果不懂,找计算机系的教材看看。
    1、先要说说我们现在地系统,我们的使用的都是32位Windows,所谓32位就是,地址的大小是32位,这就意味着,一个程序最大可以使用4G的内存。
    2、在Windows系统中,int的大小恰好也是32位。
    基于这么两点,我来说说你的运气为什么那么好!
    首先,你New一个Pointer,那么就是开了4Byte的内存,然后你强制转换为PInt,进行Int的赋值,而Int恰巧是4Byte,所以上述语句不会产生错误。如果你换成Double,保证你错。
    其次,你直接写'abc123',那么程序会在Heap中开一段内存,存放这个字符串。你的赋值,就是将这个字符串在堆中的起始地址付给那个Pointer。所以,此时并不会产生内存错误。但是,你原来New出来的地址就丢掉了,也就是所谓的Memory Leak。
    好了,说了这两点。应该不难理解:
     new(pt);  ip(pt)^:=1234;
      showmessage(inttostr(ip(pt)^));  sp(pt)^:='abc123';
      showmessage(sp(pt)^);  dispose(pt);
    没有问题,实际上最后一句Dispose写与不写,都没有任何意义。
    而前面掉个顺序为什么出错呢?
    因为此时pt已经指向那堆中的字符串,这个时候,试图向指向这个字符串地址的内存(我也不知道这个地址在哪里)写数据,就很容易出AV错误。即使不出,那么该程序如果一大,就会出一个非常难以Debug的错误。你的运气太好了,不过你要写Pointer的程序,还得修炼两年。
      

  7.   

    首先,我先声明,我就是看准了变量大小相同,才去转换它们的。这好比一个技术高超的跳楼运动员(世贸大厦9月11日自发举办了这样的运动会),从100层的楼上跳下,刚好跳到街上一辆装满衣服的货车上,结果没有死!街上的围观的人都说:“你真是运气太好了,就象中国足球队的出线一样!刚好这辆车从这过,不然你早死了,你要学会跳楼,还要两年时间!”殊不知,这个运动员正是算准了当他自己跳下快砸中地面时刚好就有装衣服的货车及时打此经过,而不是一辆满载炮弹的货车从此经过一样!其次,你说把integer改成double,保证出错,你试过了吗?不同大小之间的变量也可以互相转化,只不过,把被转化的变量的在内存的前面部分转化而己。现在我就把我的程序改一下,把integer改成double,看它出不出错!type ip=^double;//现在改了
    var  pt:^pointer;
    begin
      new(pt);//pt是一个指向pointer类型的指针
      ip(pt)^:=1234;//把pt转化成ip类型的数据,即double类型的指针!//现在改了
      //这样,ip(pt)^就变成了一个double变量,给它赋值1234.
      showmessage(floattostr(ip(pt)^));//显示出来!//也改了
      dispose(pt);
    end;运行一下,出错了没有?可能我的电脑特别烂吧,傻电脑就是不按我们的意思出错!就算我把range checking选上,提醒它也没有用的。哦,还给它选上overflow checking也是照旧的。我的电脑是delphi4.0+win2000或winme的。没钱买delphi5.0! :(
    会与delphi的版本有关的?你要用好指针吗?我看,你得再...再...想想.....想...想...上...两............
    ..........................................................................
    ..........................................................................
    ..........................................................................
    .........................................................两...两...个小时!
      

  8.   

    pt:^pointer是一个指向指针的指针,如果定义为:
    var  pt:pointer;
    肯定出错,但是上面的代码没有出问题。难道Delphi有这种自动转换的功能?
      

  9.   

    下面的代码也可以通过:type ip=^double;//现在改了
    type sp=^string;
    var  pt:^pointer;
    begin
      new(pt);//pt是一个指向pointer类型的指针
      (ip(pt))^:= 12345;
      showmessage(floattostr(ip(pt)^));//显示出来!//也改了  (sp(pt))^:= 'aa12345';
      showmessage(sp(pt)^);
      dispose(pt);
    end;真的是类型智能转换的吗?那Delphi是如何分配存储空间的呢?
      

  10.   

    To TechnoFantasy:可以注意一下pt指向的位置。
    To dedema:你走你的阳关道,我走我的独木桥。我自信领悟了指针,至于Delphi有什么蹊跷,我不关心。我知道所有的编程语言在指针上至少要执行一个相同的规则。
      

  11.   

    to chechy:
    什么“你走你的阳光道,我走我的独木桥”,岂不是说,我们今后各不相干吗?哎呀,不能这样说吧!我们在这里只不过是发表见解吧,我有某种理解,当然想弄清怎么回事的!你对指针有某种深刻的领悟,那就应该帮我们领悟一下呀!
    对以上的一些代码,我再试一下,发现奇了!第一次编绎通过后,运行起来出错。第二次编绎起来运行后又没有错。真是奇怪,任何软件总有一些bug。就算不是bug,人的世俗脑袋面对密密麻麻的机器代码,也难免出错的。不然历史上就不至于有什么软件危机了。
    对你上面的解释,凭我的智力还真的理解不了的!只好试一下执行结果后,挑你的语病来说了。希望你不要介意的!不过,我这样说好象白说,因为你本来就不会介意的!对吧!
      

  12.   

    chechy老大是指针天使
    难道你们都不知道吗
    该打
      

  13.   

    to dedema(思想恐龙) 
    如果你将
    type ip=^double;//现在改了
    type sp=^string;
    var  pt:^pointer;
    定义为全局的就会出错,下面是在DelphiBBS上得到的回答:按照原理来说,(ip(pt))^:= 12345.334是会出错的,当然(ip(pt))^:= 12345也会出错,
    FLOAT是8字节,并且也不会自动转换到SINGLE不直接出错是有原因的,NEW是从局部堆里分配空间使用
    你可以把局部堆当成是一个已经分配有地址空间的大数组,你本来是分配得到了
    其中的第N项的指针,但是你却用赋值占用了第N和N+1项的地址,当然不会引发内存访问
    冲突错误你这样不管占用空间大小的使用,只是占用了另外一些未能标记为你使用的一部分内存
    可能现在不出错,但是可能会影响其他的一些在堆中的其他变量如果你一定要这样用,将来你自己的程序就可能会出现想不到的错误
    例如你用了(ip(pt))^:= 12345.334,结果却发现本来一个一定等于1的整数变量的
    值发生了莫名其妙的变化打个比方
    TYPE TREC=PACKED TRECORD
         I:INTEGER;
         J:INTEGER;
        END;VAR REC:TREC;
    BEGIN
    REC.I:=1;
    REC.J:=2;IP(@REC.I)^:=1234;
    SHOWMESSAGE(INTTOSTR(REC.J))
    END;
    然后你再查看下,结果J的值也发生了变化,但是IP(@REC.I)^:=1234;却没引发错误.不知chechy认为是否正确。
      

  14.   

    不是呀,你的两段都出错,
    出在 sp(pt)^:='abc123';
      showmessage(sp(pt)^);
    你看看是不是呀,我还没有看完
    你门讨论,我看看
      

  15.   

    procedure TForm1.Button1Click(Sender: TObject);
    type
      ip = ^integer;
      sp = ^string;
    var
      pt: pointer;
      S: sp;
      I: ip;
    begin
      new(S);
      new(I);
      S^ := 'abc123';
      pt := S;
      showmessage(sp(pt)^);
      I^ := 1234;
      pt := I;
      showmessage(inttostr(ip(pt)^));
      dispose(S);
      dispose(I);
    end;
      

  16.   

    procedure TForm1.Button1Click(Sender: TObject);
    type ip=^integer;
        sp=^string;
    var  pt:^pointer;
    begin
      new(sp(pt)); //这里分配的空间不一定够  sp(pt)^:='abc123';
      showmessage(sp(pt)^);  ip(pt)^:=1234;
      showmessage(inttostr(ip(pt)^));  dispose(pt);
    end;
      

  17.   

    : zswang(伴水)(伤心中)  的方法可以,
    但是我想 事情可能是这样,
    我的个人感觉,大家见笑。
    PINTER是4BYTE和INTEGER一样,
    所以,P1:^POINTER 声明的
    P1 和 INTEGER的指针,是兼容的,
    所以你可以用它指向,INTEGER变量。
    但是
    分配空间之后,在让他指向STRING的指针(姑且这么说)
    他们是不兼容,偶认为
    以上是我个人理解。
    我不认为这里有指向指针的指针的说法。
      

  18.   

    为什么要  P1:^POINTER 
    为什么不  P1: POINTER 
      

  19.   

    to TechnoFantasy(www.applevb.com):
    大事不好!
    我按您的指示:
    把如下这个局部过程的声明改到全局那儿!
    type ip=^double;//现在改了
    var  pt:^pointer;
    begin
      new(pt);//pt是一个指向pointer类型的指针
      ip(pt)^:=1234;//把pt转化成ip类型的数据,即double类型的指针!//现在改了
      //这样,ip(pt)^就变成了一个double变量,给它赋值1234.
      showmessage(floattostr(ip(pt)^));//显示出来!//也改了
      dispose(pt);
    end;
    可是还是不出错的!包括编绎和执行!
    把以上声明部分的pt:^pointer,改成pt:^byte,然后写成如下形式:
    type ip=^double;//现在改了
    var  pt:^byte;
    begin
      new(pt);//pt是一个指向byte类型的指针
      ip(pt)^:=122.322224;//把pt转化成ip类型的数据,即double类型的指针!并把数字改大,占用字节数更多的。
      //这样,ip(pt)^就变成了一个double变量,给它赋值122.322224.
      showmessage(floattostr(ip(pt)^));//显示出来!//也改了
      dispose(pt);
    end;
    然后再把声明部分写到全局去,可是还是不出错的!
    我傻眼了。
    还有,局部堆的指针如以上般地转化,我写了如下的过程进行“体验”
    type ip=^dword;
    var  pt:^byte;
         r:record
           x:byte;
           y:byte;
           z:byte;
           xyz:byte;
           end;
    begin
    //  new(pt);//pt是一个指向byte类型的指针
      r.x:=1;
      r.y:=2;
      r.z :=3;
      r.xyz:=123;
      pt:[email protected];
     // showmessage(inttostr(integer(@r))+' '+inttostr(integer(@r.z)));//不一样的地址
      //showmessage(inttostr(sizeof(r)));
      ip(@r.x)^:=10*256*256*256+11*256*256+12*256+13;//把pt转化成ip类型的数据//  showmessage(inttostr(ip(pt)^));//显示出来!
      showmessage(inttostr(r.x)+' '+inttostr(r.y)+' '+inttostr(r.z)+' '+
      inttostr(r.xyz));//显示结果为13 12 11 10,为期待的结果
      //dispose(pt);
    end;
    可是把  ip(@r.x)^:=10*256*256*256+11*256*256+12*256+13;
    改成为  ip(@r.y)^:=10*256*256*256+11*256*256+12*256+13;//把pt转化成ip类型的数据
    后还是  出错了。按大富翁的回答不应出错的啊?谢谢你了。以后还要得到你的指点的。
      

  20.   

    to dedema(思想恐龙)
    上面的代码如果是^double不会出错,我估计是Delphi进行了某中转换。如果你定义了
    ^string,如下面:  type ip=^double;
      type sp=^string;var
      pt:^pointer;  //全局变量begin
      new(pt);//pt是一个指向byte类型的指针
      ip(pt)^:=122.322224;//把pt转化成ip类型的数据,即double类型的指针!并把数字改大,占用字节数更多的。
      //这样,ip(pt)^就变成了一个double变量,给它赋值122.322224.
      showmessage(floattostr(ip(pt)^));//显示出来!//也改了
      sp(pt)^:='ddddd';    //错误
      showmessage(sp(pt)^);   
      dispose(pt);end;上面的代码会导致指针错误,大富翁的回答我还觉得不是太明白,我到borland的新闻组
    上面问一下。至于你最后的代码,还没来得及研究。
      

  21.   

    new(sp(pt)); 
    new(sp(pt)); 
    new(sp(pt)); 
    new(sp(pt)); 
    new(sp(pt)); 
    new(sp(pt)); 
      

  22.   

    to dedema(思想恐龙)
    干嘛把思路搅得这样乱呢?
    编译通过执行不提示错误并不能证明什么的.
    保护模式下内存地址的保护也是有限的.