编译此代码时
{$WARNINGS ON}
function Test(s: string): string;
var
t: string;
d: double;
begin
if s = '' then begin
t := 'abc';
d := 1;
end;
Result := t + FloatToStr(d);
end;
我收到警告“变量'd'可能尚未初始化”,但我没有得到变量't'的相同警告。这似乎不一致。这段代码只是一个显示编译器警告的简单示例,但我刚刚在我的实时代码中发现了一个错误,该错误会被未初始化的字符串变量的编译时警告捕获。我可以在Delphi 6中以某种方式切换此警告吗?还是在较新版本的Delphi中?
答案 0 :(得分:12)
不,没有开关。不会发生警告,因为字符串是编译器管理类型,并且始终由编译器初始化。
答案 1 :(得分:3)
是: - )
使用短串或 pChars
{$WARNINGS ON}
function Test: String;
var
p: pChar;
d: double;
begin
Result := p + FloatToStr(d);
end;
//This code will give a warning.
<强>严重强>
不,普通的Delphi字符串和短串会自动初始化为''(空字符串)。 Shortstrings生活在堆栈上,不需要清理。其他字符串称为“托管”类型,当使用引用计数不再使用时会自动删除。
PChars,好消息
pChars只是一个指针。德尔福不管理它们
但是Delphi 会自动将它们转换为字符串,反之亦然。
pChars坏消息
如果将 pChar转换为字符串,Delphi会将pChar的内容复制到字符串中,您仍然有责任销毁pChar。
另请注意,此复制需要花费时间,如果您这样做,将会减慢代码速度。
如果将字符串转换为pChar Delphi将为您提供指向该字符串所在地址的指针。 Delphi将停止管理字符串。您仍然可以为字符串指定值,但不会再自动增长。
来自:http://www.marcocantu.com/epascal/English/ch07str.htm
以下代码无法按预期工作:
procedure TForm1.Button2Click(Sender: TObject);
var
S1: String;
begin
SetLength (S1, 100);
GetWindowText (Handle, PChar (S1), Length (S1));
S1 := S1 + ' is the title'; // this won't work
Button1.Caption := S1;
end;
这个程序编译,但是当你运行它时,你会感到惊讶:按钮的标题将包含窗口标题的原始文本,而没有添加到其中的常量字符串的文本。问题是,当Windows写入字符串(在GetWindowText
API调用中)时,它不会正确设置长Pascal字符串的长度。 Delphi仍然可以使用这个字符串作为输出,并且可以通过查找null终止符来确定它何时结束,但是如果你在null终止符之后附加更多字符,它们将被完全跳过。
我们如何解决这个问题?解决方案是告诉系统将GetWindowText
API调用返回的字符串转换回Pascal字符串。但是,如果您编写以下代码:
S1 := String (S1);
系统会忽略它,因为将数据类型转换回自身是无用的操作。要获得正确的长Pascal字符串,您需要将字符串重新转换为PChar,然后让Delphi将其重新转换回字符串:
S1 := String (PChar (S1));
实际上,您可以跳过字符串转换,因为在Delphi中PChar-to-string转换是自动的。这是最终的代码:
procedure TForm1.Button3Click(Sender: TObject);
var
S1: String;
begin
SetLength (S1, 100);
GetWindowText (Handle, PChar (S1), Length (S1));
S1 := String (PChar (S1));
S1 := S1 + ' is the title';
Button3.Caption := S1;
end;
另一种方法是使用PChar字符串的长度重写Delphi字符串的长度,写一下:
SetLength (S1, StrLen (PChar (S1)));