我发现 delphi 字符串指针严重问题

sztony 2009-11-24 10:11:53
在DELPHI 中,一般用'@+变量名’的形式,就可以获得该变量的首地址,如:
var
int: integer;
pi: ^integer;
begin
int := 100;
pi := @int;
end;


用类似上述的方法,整型、浮点型、字符型、一维数组,二维数组都能得到正确的结果,
但是,如果是字符串,则结果错误!

比如:
var
str, s: string;
pstr: ^char;
begin
s:='';
str :='abdeFGg AAA$#! 123'#0;
pstr := @str;

while p^ <> #0 do
begin
s := s +p^;
inc(p);
end;
form1.caption := s;
end;


该程序遍历字符串时,则不能正确得出结果,但如果把 pstr := @str; 改为 pstr := @str[1]; 则可以,

这说明DELPHI 在指针使用上,比较混乱,没有严格统一的定义,既然数组都可以'@+变量名'形式,为何单独字符串就不能用
'@+变量名'呢?非得要指定第一下标呢?这样非常容易造成使用错误和困惑。

所以,我觉得,OBJECT PASCAL 应该严格统一指针的使用定义!以免造成使用者的困惑不解。

















...全文
569 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamduo 2009-11-24
  • 打赏
  • 举报
回复
#8
声明的指针不一样,不能兼容说明严格。
声明的类型不一样,但是可用,这是强制转换的结果,说明D人性化。
难道说,你希望第二段代码不通过才算是好吗?
在D中,本来指针就属于高手级别的东西了。
不会跟拖拖控件那么简单的。
#1
你很有心。pstr := @str[1]; 还知道用1来试试看。
通常我对string是不会做指针处理的。就算要处理,也先赋值给PChar变量,在处理。
string的0表示的Length(以前),所以,真正的string开始确实是第一个。

好好研究下,知道我不知道的时候,请指教我。
sztony 2009-11-24
  • 打赏
  • 举报
回复
同样的问题还存在数组中,比如我定义二个数组
var
arr1:array of char;
arr2:array of char;
begin
... ...
arr2 := arr1;
... ...
end;

这样就不行,但如果写在同一行,如

var
arr1,arr2:array of char;

这样就可以相互赋值,是在令人难以理解

所以,我认为,DELPHI/PASCAL应该纠正这些问题,获得统一,明确的定义
sztony 2009-11-24
  • 打赏
  • 举报
回复
既然 string 本身就是一个地址,那么就应该直接可以它的变量名获取地址,比如:

var
p:^char;
str:string;
begin
p := str;
end;

但却不可以,
而C语言就明确统一,只要是指针类型,类型相同,就直接可以用名称获得首地址,比如数组,在C语言中就可以用 p = arr;这样的形式,

同样,如果定义一个指针字符串 *str,那么就直接可以用 p = str来取得首地址,并没有象PASCAL那样用
&str[0]的方式。

我们再来看一个更搞笑的:

type
Ptchar = ^char;
var
p : ^char;
p2 : Ptchar;
begin
... ...
p2 = p ;
... ...
end;

同样是字符指针,但却不行,说类型不兼容。
但如果不是指针,用字符,或者整数其他类型,却可以,如:

type
tchar = char;
var
ch :char;
tch:tchar;
begin
... ...
ch := 'A'
tch := ch;
... ...
end;

而这样,却又可以兼容,得出正确的结果。




所以,PASCAL/DELPHI的指针确实是个比较混乱,容易使人迷惑困惑,我认为,这是PASCAL/DELPHI语言
本身的缺陷。







liangpei2008 2009-11-24
  • 打赏
  • 举报
回复
先搞清楚string与多维数组的实现方式再来讨论"Delphi指针混乱"也不迟:)
SuperTitan001 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wzwcn 的回复:]
你可能没注意到,String本身也是个指针,所以你@Str得到的不是它指向的首地址,而是Str指针本身的地址。
[/Quote]

嗯,同意
string其实是一个指向储存字符串内存地址位置的指针
而pchar是指向那个字符串开头内存地址的指针
所以在赋值的时候用pstr := @str[1]才可以。
wzwcn 2009-11-24
  • 打赏
  • 举报
回复
所以想取它指向的首地址,要么直接转换,比如pchar(str),要么@str[1]
Seamour 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用楼主 sztony 的回复:]
在DELPHI 中,一般用'@+变量名’的形式,就可以获得该变量的首地址,如:
var
  int:  integer;
  pi:  ^integer;
begin
    int := 100;
    pi  := @int;
end;


用类似上述的方法,整型、浮点型、字符型、一维数组,二维数组都能得到正确的结果,
但是,如果是字符串,则结果错误!

比如:
var
  str, s: string;
  pstr: ^char;
begin
    s:='';
    str :='abdeFGg  AAA$#! 123'#0;
    pstr := @str;

    while p^ <> #0 do
    begin
        s := s +p^;
        inc(p);
    end;
    form1.caption := s;
end;


该程序遍历字符串时,则不能正确得出结果,但如果把    pstr := @str;  改为    pstr := @str[1];  则可以,

这说明DELPHI 在指针使用上,比较混乱,没有严格统一的定义,既然数组都可以'@+变量名'形式,为何单独字符串就不能用
'@+变量名'呢?非得要指定第一下标呢?这样非常容易造成使用错误和困惑。

所以,我觉得,OBJECT PASCAL 应该严格统一指针的使用定义!以免造成使用者的困惑不解。



[/Quote]
一看你就没试明白,还什么一维二维数组都如何如何,以后就等着出错去吧。自己用不明白指针还怪上语言了
wzwcn 2009-11-24
  • 打赏
  • 举报
回复
你可能没注意到,String本身也是个指针,所以你@Str得到的不是它指向的首地址,而是Str指针本身的地址。
sztony 2009-11-24
  • 打赏
  • 举报
回复
不好意思,上面第二段代码,有些字打错了,要把P改为PSTR,
haitao 2009-11-24
  • 打赏
  • 举报
回复
string本来就是特殊的机制实现的,
简单的是 长度+实际字符串
复杂的是 引用数+长度+实际字符串
国风 2009-11-24
  • 打赏
  • 举报
回复
是楼主主观意识在作怪
用惯了Delphi再去用VC也会碰到类似的情况
但不能说明这个语言有问题
abc518048 2009-11-24
  • 打赏
  • 举报
回复
要这样用
var
s: String;
p: Pointer;
begin
s := 'abc';
if s <> '' then
p := @s[1]
else
p := nil;
end;
wliaoc 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wzwcn 的回复:]
你可能没注意到,String本身也是个指针,所以你@Str得到的不是它指向的首地址,而是Str指针本身的地址。
[/Quote]

正解
Seamour 2009-11-24
  • 打赏
  • 举报
回复
不按照你的想法来就叫不严谨了?凭啥严谨不严谨由你来决定?自己不会用反倒还赖上编译器了?
sztony 2009-11-24
  • 打赏
  • 举报
回复
我学艺不精是一个方面,但一种语言,把很多东西搞成那么多歧义,使人迷惑,也不是应该吧。

PASCAL虽然是严谨,但有时候严谨,有时候又不严谨,那不是有问题么?就象我前面说的,如果自定义一个指针字符类型,则与一般指针字符类型不兼容, 但自定义一个字符类型,又可以与系统字符类型兼容,这不让人混乱,迷惑么?

nhconch 2009-11-24
  • 打赏
  • 举报
回复
Delphi一点问题也没有,是你学艺不精
武稀松 2009-11-24
  • 打赏
  • 举报
回复
字符串已经是结构体指针了呀.
@字符串,不过是指针的指针而已.
Delphi2009以前
type
PStrRec = ^StrRec;
StrRec = packed record
refCnt: Longint; //引用计数
length: Longint; //长度
data : array[1..length] of char;
end;
Delphi2009以后
type
PStrRec = ^StrRec;
StrRec = packed record
codePage: Word; //代码页
elemSize: Word; //元素大小
refCnt: Longint; //引用计数
length: Longint; //长度
data : array[1..length] of char;
end;
Harryfin 2009-11-24
  • 打赏
  • 举报
回复
var
arr1:array of char;
arr2:array of char;
begin
... ...
arr2 := arr1;
... ...
end;

----------------------------------------

我答这个问题。DELPHI是强类型的语言,array of char只是声明一个动态数组,它不是一个具体的类型。你必须这样声明:

type
TArrayType = array of char;

var
arr1: TArrayType;
arr2: TArrayType;
begin
... ...
arr2 := arr1;
... ...
end;
wzwcn 2009-11-24
  • 打赏
  • 举报
回复
Delphi类型要求很严格,所以
Type
Tc=^char;

var a:Tc;
b:^char;

这样虽然我们看起来a和b类型是一样的,但它却认为两个不同的类型
林石公 2009-11-24
  • 打赏
  • 举报
回复
嗯....
真是让人难以理解
加载更多回复(1)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧