Наиболее просто устроен тип ShortString
. Это массив символов с индексами от 0 до N , где N — число символов, указанное при объявлении переменной (в случае использования идентификатора ShortString
N явно не указывается и равно 255). Нулевой элемент массива хранит текущую длину строки, которая может быть меньше или равна объявленной (эту длину мы будем далее обозначать M ), элементы с индексами от 1 до M — это символы, составляющие строку. Значения элементов с индексами M +1.. N не определены. Все стандартные функции для работы со строками игнорируют эти символы. В памяти такая переменная всегда занимает N +1 байтов.
Ограничения типа ShortString
очевидны: на хранение длины отводится только один байт, поэтому такая строка не может содержать больше 255 символов. Кроме того, такой способ записи длины не совпадает с принятым в Windows, поэтому ShortString
несовместим с системными строками.
В системе приняты так называемые нуль-терминированные строки: строка передается указателем на ее первый символ, длина строки отдельно нигде не хранится, признаком конца строки считается встретившийся в цепочке символов #0
. Длина таких строк ограничена только доступной памятью и способом адресации (т.е. в Windows теоретически это 4 294 967 295 символов). Для работы с такими строками предусмотрен тип PChar
. Переменная такого типа является указателем на начало строки. В литературе нередко можно встретить утверждение, что PChar = ^Сhar
, однако это неверно: тип PChar
встроен в компилятор и не выводится из других типов. Это позволяет выполнять с ним операции, недопустимые для других указателей. Во-первых, если P
— переменная типа PChar
, то допустимо обращение к отдельным символам строки с помощью конструкции P[N]
, где N
— целочисленное выражение, определяющее номер символа (в отличие от типа ShortString
, здесь символы нумеруются с 0, а не с 1). Во-вторых, к указателям типа PChar
разрешено добавлять и вычитать целые числа, смещая указатель на соответствующее число байтов вверх или вниз (здесь речь идет только об операторах "+" и "-"; адресная арифметика с помощью процедур Inc
и
Dec доступна для любых типизированных указателей, а не только для PChar
).
При работе с PChar
программист целиком и полностью отвечает за выделение памяти для строки и за ее освобождение. Именно это и служит основным источником ошибок у новичков: они пытаются работать с такими строками так же, как и с AnsiString
, надеясь, что операции с памятью будут выполнены автоматически. Это очень грубая ошибка, способная привести к самым непредсказуемым последствиям.
Хотя программист имеет полную свободу выбора в том, как именно выделять и освобождать память для нуль-терминированных строк, в большинстве случаев самыми удобными оказываются специально предназначенные для этого функции StrNew
, StrDispose
и т.п. Их преимущество заключается в том, что менеджер памяти выделяет чуть больше места, чем требуется для хранения строки, и в эту дополнительную память записывается, сколько байтов было выделено. Благодаря этому функция StrDispose
удаляет ровно столько памяти, сколько было выделено, даже если в середину выделенного блока был записан символ #0
, уменьшающий длину строки.
Компилятор также позволяет рассматривать статические массивы типа Char
, начинающиеся с нулевого индекса, как нуль-терминированные строки. Такие массивы совместимы с типом PChar
, что позволяет обойтись без использования динамической памяти при работе со строками.
Тип AnsiString
объединяет достоинства типов ShortString
и PChar
: строки имеют фактически неограниченную длину, заботиться о выделении памяти для них не нужно, в их конец автоматически добавляется символ #0
, что делает их совместимыми с системными строками (впрочем, эта совместимость не абсолютная; как и когда можно использовать AnsiString
в функциях API, мы рассматривали в разд. 1.1.13. ).
Переменная типа AnsiString
— это указатель на первый символ строки, как и в случае PChar
. Разница в том, что перед этой строкой в память записывается дополнительная информация: длина строки и счетчик ссылок. Это позволяет компилятору генерировать код, автоматически выделяющий, перераспределявший и освобождающий память, выделяемую для строки. Работа с памятью происходит совершенно прозрачно для программиста, в большинстве случаев со строками AnsiString
можно работать, вообще не задумываясь об их внутреннем устройстве. Символы в таких строках нумеруются с единицы, чтобы облегчить перенос старых программ, использовавших строки типа ShortString
.
Читать дальше
Конец ознакомительного отрывка
Купить книгу