变量可能尚未初始化。我可以为字符串切换此警告吗?

时间:2011-04-24 13:40:51

标签: delphi compiler-warnings initialization

编译此代码时

{$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中?

2 个答案:

答案 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)));