这项有礼了! (200分)

  • 主题发起人 主题发起人 党sir
  • 开始时间 开始时间

党sir

Unregistered / Unconfirmed
GUEST, unregistred user!
请问
1、pchar和^char的区别?
2、我下面的程序为什么不正确?
; ;str:string;
; ;p:^char;
; begin
; str:='sdfsadf';
; p:=@str[1]
; end;
 
这是正常的,你更改一下这个字段的类型,我忘记了ACCESS有什么类型了,最好是与DECIMAL
相近的,如NEMBER等,能够限制小数点位数的类型。
不知道你的是什么类型。
 
; ;BDE有这个缺陷,ADO好象没有此问题。
 
我可以正常通过你的代码,请问楼上两位的是什么意思?
 
编译能够通过,但执行不了,各位试一试!
 
PChar就是^Char;
PChar是这样定义的
Type PChar=^Char;
PChar类型是一个指向Char的指针,并使用Delphi的扩展语法.它也能够作为一个String或者
是一个Char数组指针来对待.
var ;str:string;
; ;p:^char;//等于PChar
; ;x:Char;
begin
; str:='sdfsadf';
; p:=@str[1];//得到'sdfsadf'因为是指针,而且从第一个开始,所以是整个字符串
; x:=str[1];//得到's'一个字符,第一个,s
; p:=@str[2];//得到'dfsadf'从第二个开始,
; x:=str[2];//得到'd'第二个,为d
; ShowMessage(string(p));
; showmessage(x);
end;
这样解释,不知你清楚了没有?
 
张兄,谢谢你的指引,我明白了一些,还有如下一个问题:
1、
var
; pc:pchar;
; p:^char;
; str:string;
begin
; str:='sadfasdf';
; p:=@str[1];
; pc:=p;//这里出错!我想把指针赋值给一个pchar,既然pchar=^char,为什么还要
; ; ; ; //改成pc:=pchar(p)才能够通过?
end;

end;
2、
;反过来呢?p:=pc也通不过!
3、
;你的例子很好,我修改一下:
; p:=@str;
; 请问,这时候p指到什么地方?

多谢指教,好人呀
 
1,2
; ;pc:=p;或pc:=p;出错是很正常的,虽然pchar与^char其实就是一个东西,但不是同一个类型(Type)
; ;delphi不认为它们可以互相通用。
; ;这句 Type PChar=^Char; 使得在delphi中pchar与^Char属于不同的类型。你找一本讲语法的书看一看,
3.
; p:=@str; 等价于 p:=@str[1];
;
 
我不同意小人物的看法:
; p:=@str; 等价于 p:=@str[1];
; 我们可以试验一下,看看
var
; c:char;
; p:^char;
; str:string;
begin
; str:='12345';
// 1、
; p:=@str;
; c:=p^;//c<>'1'
// 2、
; p:=@str[1];
; c:=p^;//c='1'
end; ;
 
delphi对语法校验比较严,虽然出于一个声明,但他不认为是相同类型
 
同意楼上的看法。[^]
 
第一个问题正如 yamazeki据说的那样 但你可以通过类型转换来实现

其实在delphi 中 string 类型的的变量本身也是一个指针
所以会出错[ 党sir ]所说的情况

[小人物] 说的哪种情况是在 数组时它是成立
 
1.2是同理.
PChar和^Char是相同类型,但它们是指针.指针只是指明地址所在,所以你直接赋值就不能实
现,而你加上PChar(p)则是将其变为字符串指针,

3.我们指明类型为string时,实际上是默认的AnsiString类型.(String分两种类型,下面有介绍)
Delphi会把AnsiString存储成一个指向记录的指针,但该指针指向记录的Data成员的开始
地址,而不是记录本身的开始地址,所以直接调用@string得到的并不是它数据的开始地址,而
只是string的开始地址.即string实际上也是指针,所以它用PChar也很好就将String转换为
PChar,而Char是代表具体的字符,所以若你的资料是Char(下面有例子),你直接调用@string
时就不会出错.

下面是找到的一点资料.
string分两种,一种是与Pascal传统string相兼容,叫ShortString,
; 它的存储结构如下:
; ;+---------------------+ ;
; ;| 1Byte | ;字符串内容 |
; ;+---------------------+
; ;0 ; ; ; 1 ......
; ; 其中第一个字节为字符串的长度。
; ; 所以ShortString所能包括的字符串长度不能大于255。
; 另一种是叫长字符串AnsiString, ;它就是一个指向字符串的指针,不过具体的存储有些特别。
; 它的存储结构如下:
; +-----------------------+
; | 4B | 4B | ;字符串内容 |
; +-----------------------+
; -8 ; -4 ; 0 ;......
; 其中,AnsiString指向字符串第一个字符,
; 在第一个字符的反方向第1到第4的4个字节表示字符串长度,第5到第8的4个字节表字符串
被引用的次数。

例子:
procedure TForm1.Button3Click(Sender: TObject);
var ;str:Shortstring;//返回'.sdfsadf',前面多一个点,因为是从1字节开始的,而第1字节是其长度并不是实际内容.
//var str:string;//我们选的string,实际上是AnsiString;//这是出的乱字符
//var ;str:array[0..7] of Char;//返回值是正常的
; ;p:^char;
; ;x:Char;
; ;P1:PChar;
begin
; str:='sdfsadf';
; p:=@str;
; p1:=PChar(p);
; x:=str[2];
; ShowMessage(string(p));
; showmessage(string(p1));
end;
 
小人物讲的1、2点没有问题,3点则有个小问题
如果把str 声明为字符数组 str: array[1..5]of char 那么两者就等价了。
问题出在delphi的 string 这个类型,它是一个指向堆栈中的字符串结构的指
针,这个结构在内存中的分配情况是 ; 分配大小-引用记数-长度-数据-#0
正是有一些额外的开销,才使string能实现生存期自管理的特性。
而字符数组和字符指针pchar则比较类似,他们都直接指向内存的一块连续的数据。
因此,不能简单地理解为字符数组pchar(或 ^char)。在DELPHI中,可以直接把pchar
赋值给string,但其实delphi内部做了转换工作。反过来把string 转换为pchar则
需要显式地转换。
所以,对str : array of char; ;str和str[1]都指向第一个数据单元。
而对 str:string; ;str[1]指向第一个数据单元,str则不是
以上是我个人理解,不一定都对,交流交流
 
to ;[阿土公公]
; string 不一定全部保存在堆栈中
当string 为shortstring 时才保存在堆栈中
当它为ansi 字符串或 ;在{$H+}编译状态下 string 在内存中
 
to 张兄,你好,你的贴子很好,我好好研究了一下,发现如下迷惑之处:

你的例子我做了试验后发现:
例子1、
procedure TForm1.Button3Click(Sender: TObject);
var ;
; ;str:Shortstring;
; ;p:^char;
; ;P1:PChar;
begin
; str:='sdfsadf';
; p:=@str;
; p1:=PChar(p);
; showmessage(string(p1));
end;
的结果不是'.sdfsadf',而是'sdfsadf-魒B',得到的第一个没有显示的字符经过监测是
ASCII码7,也就是字符串的长度,但是' sdfsadf'后面又跟了一些乱字符,不知为什么?

我自己做的实验2:
var
; str:string;
begin
; str:='12345'+#0+'67890';
; showmessage(str);
end;
结果显示是'12345',是否可以验证shortstring型也是按照null结束的,那么其前面的
一个保存长度的字节不久多余了?

我的理解是:
既然str是shortstring型的,那么,读取shortstring时候,系统既参考第一个字节,又
; 兼顾了字符串中的null,取二者的较小值为字符串的实际长度,不知是否正确?
; 如果这个理论正确的话,例子1的结果又没法解释了。
我好困惑!我好彷徨!我断断续续学了几年的delphi,现在回过头来重新温故,发现自己
原来还是个小学生!
 
后退
顶部