3

我写了这段代码,并在其中获得了 AV。

  procedure TForm1.Button1Click(Sender: TObject);
  Var
     C : Pchar;
     s : string;
 begin
    c:= PChar('*');
    s := string(c); // AV here , but code works if i put C:= PChar('**') 
   ShowMessage(c);
end;

我不知道为什么。有人知道吗?

提前致谢。

4

3 回答 3

10

使用单字符字符串文字,您输入的是 a Char,而不是 a string,因此它不是指针。当你将它转换回来时,它仍然不是真正的指针,尽管它声明了类型,所以它不能转换为字符串。

如果您发现自己键入转换字符串文字,您可能在做一些不必要的事情。尽管您可以提示它应该使用哪种类型,但正如此处的其他答案所展示的那样,编译器已经检测到文字需要具有哪种类型,并且通常是正确的。只需将文字直接分配给变量,无需任何转换。

如果您完全省略类型转换,您的代码对于您想要的任何长度的字符串都同样适用:

// All PChar assignments, no casting
c := '';
c := '*';
c := '**';

此外,也不需要强制返回string。可以直接赋值 a PChar,编译器会自动进行转换:

s := c;
于 2013-06-19T13:55:58.360 回答
3

实际上,

c:= PChar('*');

编译为

mov [c],$0000002a

好像是这样写的:

c:= PChar(ord('*'));

由于,字符ord('*')=$2a似乎被强制转换为整数 ( ),因此该整数被转换为指针。所以当你试图访问内容时,你访问的内存地址是无效的,并触发了访问冲突。'*'NativeIntc$0000002a

编译时:

c:= PChar('**');

它生成为

   mov eax,$00548984
   mov [c],eax

string在这种情况下,编译器在可执行文件中生成一个以#0 结尾的常量文本缓冲区(而不是 Delphi ),并c设置为其地址。

PChar('*')行为不一样的事实是类型的一种“优化” char,可以将其类型转换为整数。
但我知道这可能会令人困惑。

如果你只想要一个指向单个 '*' 的指针,你可以写:

c:=PChar('*'#0);
c:=PChar(string('*'));

这将按预期工作,因为两者都会绕过强制转换为字符序数值。

于 2013-06-20T06:52:29.933 回答
2

AV 意味着对内存的错误处理。从无处获取数据或写入无处。

问题来自不同类型的数据。

'*'

是 Char,但是

'**'

是字符串

这将适用于您的代码:

 procedure TForm1.Button1Click(Sender: TObject);
 Var
    C : Pchar;
    s : string;
 begin
    c:= PChar(string('*'));
    s := string(c); // AV here , but code works if i put C:= PChar('**') 
   ShowMessage(c);
end;
于 2013-06-19T14:11:44.120 回答