Возможно, переменная не была инициализирована. Могу ли я включить это предупреждение для строки?
когда я компилирую этот код
{$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? Или в более новой версии Дельфи?
2 ответов
нет, для этого нет переключателя. Предупреждение не возникает, поскольку строка является управляемым типом компилятора и всегда инициализируется компилятором.
да :-)
использовать shortstrings или 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.
Также обратите внимание, что это копирование занимает время, и если вы делаете это много замедлит ваш код.
если вы конвертируете string к pChar Delphi даст вам указатель на адрес, в котором живет строка. И !! Delphi перестанет управлять строкой. Вы все еще можете назначить значения строке, но она больше не будет автоматически расти.
From: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 все еще может использовать эту строку для вывода и может выяснить, когда она заканчивается, ища нулевой Терминатор, но если вы добавляете дополнительные символы после нуль-Терминатор, они будут пропущены.
как мы можем решить эту проблему? Решение состоит в том, чтобы сообщить системе преобразовать строку, возвращаемую GetWindowText
API-вызов строки Pascal. Однако, если вы напишете следующий код:
S1 := String (S1);
система проигнорирует его, потому что преобразование типа данных обратно в себя является бесполезной операцией. Чтобы получить правильную длинную строку Pascal, вам нужно преобразовать строку в PChar и позволить Delphi преобразовать ее обратно снова правильно к строке:
S1 := String (PChar (S1));
На самом деле, вы можете пропустить преобразование строк, потому что преобразования PChar в строку в Delphi являются автоматическими. Вот окончательный код:
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;
альтернативой является сброс длины строки Delphi, используя длину строки PChar, написав:
SetLength (S1, StrLen (PChar (S1)));