вопрос | ответ |
// ПРЕДУПРЕЖДЕНИЕ: ПЛОХОЙ ПРИМЕР function WindowsDirectoryAsPChar: PChar; var Buffer: array[0..MAX_PATH] of Char; | Однако, это не будет работать. Потому что Buffer является локальной переменной, хранящейся целиком в локальной памяти (процессорном стеке). Как только |
Обычно строковые буфера имеют размер достаточный только для того, чтобы вместить лежащий в них (присвоенный им) текст. Но используя SetLength, вы може | function WindowsDirectory: string; begin SetLength(Result, MAX_PATH); GetWindowsDirectory(PChar(Result), Length(Result) |
Не забывайте, что переменная AnsiString является указателем на текст, а не самим текстовым буфером. Если текст изменяется, то он будет скопирован в др | // ПРЕДУПРЕЖДЕНИЕ: ПЛОХОЙ ПРИМЕР var S: string; P: PChar; begin S := ParamStr(0); // напр |
Строки (String), с другой стороны, намного проще использовать. Большинство вещей выполняется автоматически, само собой. Но множество API функций Windo | var S: string; begin S := ExtractFilePath(ParamStr(0)) + 'MyDoc.doc'; ShellExecute(0, 'open', PChar(S), nil, ni |
PChar и символьные массивы довольно тяжело использовать. | В большинстве случаев вы должны выделять память и не забывать её освобождать. Если вы хотите добавить текст, то вы должны сперва посчитать длину получ |
Массив типа A полезен как буфер для небольших строк или строк, ограниченных сверху (т.е. для которых известен максимальный потенциальный размер), но ч | Вы также можете использовать тип String в Delphi в качестве буфера, но, прежде чем я опишу, как это сделать, я бы сперва хотел обсудить этот тип |
это не скопирует текст 'Delphi' в массив A. Первая строка после begin нацеливает указатель S на массив A, но тут же мы, во второй строке, изменяем S т | В конкретно этом случае нам очевидно, что строка 'Delphi' влезет в массив (101 символ как-никак), так что использование StrLCopy выглядит немного пере |
// ПРЕДУПРЕЖДЕНИЕ: ПЛОХОЙ ПРИМЕР var S: PChar; A: array[0..100] of Char; begin | это не скопирует текст 'Delphi' в массив A. Первая строка после begin нацеливает указатель S на массив A, но тут же мы, во второй строке, изменяем S т |
Динамические массивы (dynamic arrays) | До Delphi 4 в языке не было динамических массивов, но они существовали как концепция. Динамический массив - это блок выделенной памяти, которая управл |
Всегда гарантируйте, что каждый вызов New() будет иметь пару в виде вызова Dispose() с тем же самым значением и типом указателя | , в противном случае память может быть освобождена неверно или не до конца. |
Вместо использования New и Dispose вы можете спуститься на уровень пониже и использовать GetMem и FreeMem. Но подпрограммы New и Dispose имеют несколь | вместо GetMem и FreeMem, там, где это возможно. |
New() - это псевдофункция компилятора. Она резервирует память для базового типа PI и записывает адрес на эту память в указатель PI. У самой переменной | PI^ := 12345; ListBox1.Add(IntToStr(PI^)); // куча кода Dispose(PI); end; |
Анонимные переменные (прим. пер.: не путать с захваченными переменными в анонимных методах) | В предыдущих примерах переменные объявлялись только там, где они были необходимы. Иногда вы не знаете, понадобится ли вам переменная или как много пер |
Обычно полезно определять типы для используемых в программе указателей. Например, вы не можете использовать ^Integer при указании типа параметра подпр | type PInteger = ^Integer; procedure Abracadabra(I: PInteger); |
Присваивание с использованием указателей происходит немного иначе, чем при прямом присвоении переменной. Обычно для работы у вас будет только указател | Это записывает число 98765 ($000181CD) в место памяти, занимаемое переменной J. Но чтобы получить доступ к этой памяти через указатель Q, вы должны ра |
Хотя вы навряд ли увидите псевдофункцию Addr в реальном коде, она полностью эквивалентна @. Однако у @ есть недостаток: если его применять к сложному | P := @PMyRec^.Integers^[6]; Q := Addr(PMyRec^.Integers^[6]); >>>> Прим. пер.: поэтому |
В простом примере выше P имеет тип Pointer. Это означает, что P содержит адрес, но вы не знаете, переменная какого типа лежит по этому адресу. Вот поч | var Q: ^Integer; |
что бы получить адресс в памяти (указатель на переменную) конкретной переменной, используется оператор взятия адреса @ или эквивалентную функционально | var pX : Pointer; i: integer; begin i := 34; pX := @i; // pX := Addr(i); end; |