![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Глупый вопрос: Pchar ->string [D6, WinME]
pavel_ak © (2002-12-14 21:04:00)Была же простая функция для перевода PChar в string. Но я ее забыл. В helpe искал - не нашел. Может кто вспомнет навскидку?
Danlicha (2002-12-16 12:42:00) [21]Да, чуваки, клёво! И, кстати, никто не отменял ShortString - я его использую везде, где только можно, т.к. глупо для строки в несколько символов выделять большой стринг, с восьми или двеннадцитибайтным заголовком. И не медленне работает, чем сишные. Но надёжно.
Ihor Osov'yak (2002-12-16 12:31:00) [22]сорри, в (16.12.02 12:23) подразумевается конечно не widestring :-)
Ihor Osov'yak (2002-12-16 12:23:00) [23]В дополнение :-)
> Просто хотелось бы иметь длинные строки без подсчета ссылок,
> вот и все.
А раскажите, пожалуйста, как себе Вы представляете реализацию
s:=s+"qwerty" где s - длинная строка без механизма подсчета ссылок и с кооректным освобождением памяти от "старого екзампляра" тела строки...
Зы и еще - перед тем как кому-то советовать прогнать Ваш код в отладчике, следовало бы это делать самому ...
vedmed (2002-12-16 12:21:00) [24]2 Sha ©
В WideString нет подсчета ссылок, для типа string есть процедура UniqueString
Ihor Osov'yak (2002-12-16 11:35:00) [25]2 Sha © (16.12.02 11:24)
Мил человек, а я так и делал, перед тем как писать сюда...
Хотя что там не все чисто догадался и теоритически ... :-)
Sha (2002-12-16 11:31:00) [26]2 han_malign © (16.12.02 10:50)
Я лишь описал некоторые тонкости применения строковых типов.
Никакого возмущения нет и в помине. Дельфи форэва !!!
Просто хотелось бы иметь длинные строки без подсчета ссылок, вот и все.
Sha (2002-12-16 11:24:00) [27]2 Ihor Osov"yak © (16.12.02 10:38)
2 han_malign © (16.12.02 10:50)
А вы попробуйте исполнить мой код, поставьте брекпойнт в начале процедуры, посмотрите память, а потом говорите про ошибки.
KSergey (2002-12-16 11:11:00) [28]Спасибо всем! Для меня было очень познавательно.
PS: люди, откуда вы все знаете?? впрочем, это риторический вопрос.
han_malign (2002-12-16 10:50:00) [29]2 Sha - ошибочка у вас закралась и вы ввели в заблуждение публику
procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:=t; //!!! r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;
- тогда будет так как вы сказали, но только для случая прямого приведения типов(что всегда делается исключительно на свой страх и риск), если сделать t[1]:="-" то для t автоматически будет выделен новый блок памяти и скопирована страрая информация.
!!!!ВНИМАНИЕ - ДЛЯ ОТКРЫТЫХ МАССИВОВ, ПРИ ИЗМЕНЕНИИ, АВТОМАТИЧЕСКОЕ РАЗДЕЛЕНИЕ ССЫЛОК ПРОИСХОДИТЬ НЕ БУДЕТ - это специально описано в хелпе, к открытым массивам надо изначально относиться как к указателям(причем Length(OpenArray)=0 можно проверять и таким способом - OpenArray=nil), только со своими функциями управления памятью и автоматическими приведением типа и адрессацией.
З.Ы. Честно говоря не понимаю возмущения, за вас сделали всю работу по управлению памяти, причем интеллектуальнальному управлению(программа активно работающая с string, IMHO надежней чем с PCHAR, поскольку когда вы отладите свою программу по поводу утечек памяти - не известно, а string-и отлажены уже давно и проверены на тысячах комерческих проектах). String - это тот-же PChar (s[Length[s]+1]=#0 - всегда), только добавлено неявное поле DWORD(pointer(DWORD(s)-4)^)=Length(s), плюс механизм ссылок. Для явного разделения ссылок достаточно сделать SetLength(t,Length(t)).
З.З.Ы. Причем механизм подсчета ссылок это не эксклюзив string-ов, этот механизм изначально зашит в Delphi-ийский менеджер кучи, только не везде используется(string, Interface). Так-что работая с PChar через GetMem/FreeMem/New/Dispose - вы все равно его используете, но в холостом режиме.
З.З.З.Ы. Причем работает и WideString:=String и String:=WideString, только что убедился что даже корректно(для интернацинальных - кодировку в старшем байте проставляет).
Ihor Osov'yak (2002-12-16 10:38:00) [30]2 Sha © (16.12.02 09:19)
У Вас, во первых, присутствует как минимум, две ошибки.
Обо всем попорядку.
Во первых: строки-константы размещаются в учаске памяти, имеющей атрибут рид-онли и механизм подсчета ссылок для них блокирован (запустите на трассирование фрагмент
s:="qwerty";
t:="qwerty";
r:="qwerty";
в режиме "CPU" (там, где дисассемблер - Ctrl+Alt+C), одновреммено проссматривая участок памяти, где живет наша "qwerty" - понятное дело, прихопив восемь байт перед началом тела строки... Вы увидите, что счетчик юзаний не меняется, он вообще установлен в $FFFFFFFF...
Вторая - вылет в следуещем фрагменте:
pc:=PChar(t); pc^:="-";ShowMessage(r);
Здесь оператор присваивания вызовет ошибку. Ибо pc будет указывать та "оригинальную строку", размещенную в "рид-онли" участке памяти...
Ps, в чем с Вами согласен, что борланд немного перемудрил со строками... Хотя вряд-ли можно было придумать что-либо лучшее.
А если вспомнить, что string=AnsiString=поинтер на структуру - то все встает на свои места... Жаль только, что практически все книги не уделяют должного внимания этому вопросу ... Отсюда и куча непоняток в тех начинающих, которые начинают выходить из уровня "ламерства"... А если чел еще не дружит Ctrl+Alt+C - проблема для него может быть очень серьезная ...
ЗЫ2 - а пимер Вы действительно хорошийц привели ... Если не брать во внимание нескольких тех неточностей, упрмянутых выше
Sha (2002-12-16 09:19:00) [31]2 xyz © (16.12.02 00:41) и других "продолжающих".
Обсуждая PChar, мы забыли про ребенка.
Сначала маленькая загадка.
Попробуйте угадать, что выведет на экран простейшая программа:
procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;
Теперь пространный ответ для начинающих.
Разработчики Дельфи "улучшая" старый короткий строковый тип, почему-то думали,
что нам вечно будет не хватать памяти и вынудили программистов пользоваться
скрытым механизмом подсчета ссылок на строки. Может это и здорово, но в моих
программах почему-то раз в 100 чаще оказывается, что ссылки посчитывать
как раз не надо.
Хотя бы дали возможность выбора или ввели новый тип. В результате этого
идиотизма стало просто невозможно написать эффективную программу, работающую
с отдельными символами строк (типа String, разумеется).
Где выход,- спросите вы. Да, да, вы знали: надо использовать PChar.
При его использовании в подобных программах эффективность возрастает в десятки
раз: не надо подсчитывать ссылки, не надо получать уникальные строки.
Пример приводить не буду. Тут пару дней назад кто-то не сделал домашнего
задания (перебор всех слов из заданного множества букв).
Если надо, найдите его - там есть пример. Если сам найду, подниму.
А как же обещанный ответ?
После выполнения первых трех операторов все строки (s, t, r) будут не просто равны.
Они будут одной строкой, использованной 3 раза, т.е. будут располагаться по одному адресу.
Первый ShowMessage покажет "qwerty", т.к. в результате оператора pc:=@s[1]
произойдет обращение за уникальной строкой и s будет располагаться уже не там,
где r и t, хоть они и будут оставаться равными. И, значит, изменение первого
символа строки s никак не повлияет на строку r.
Второй ShowMessage покажет "-werty", т.к. pc:=PChar(t) не обращается за
уникальной строкой, и, изменяя t, мы меняем r.
Почувствуйте разницу, и пребудет с вами сила.
Sha (2002-12-16 09:16:00) [32]2 Jeer © (16.12.02 00:16)
У меня случается, что в строках String лежат целые числа.
Для их побайтной обработки, например, так:
(a+i)^:=(a+i+1)^ xor (a+i+2)^ xor (a+i+3)^;
логичнее использовать PChar, а не PByte.
Здесь все a - байты целого числа, являющегося элементом
массива с индексом, равным i div 4.
xyz (2002-12-16 00:41:00) [33]из-за String и PChar столько шуму...
Jeer (2002-12-16 00:16:00) [34]Sha © (15.12.02 23:33)
Возможно, если забыть о предопределенных
IntegerArray = array[0..$effffff] of Integer;
PIntegerArray = ^IntegerArray;
PSmallInt = ^SmallInt;
PInteger = ^Integer;
PSingle = ^Single;
PDouble = ^Double;
PDate = ^Double;
PDispatch = ^IDispatch;
PPDispatch = ^PDispatch;
PError = ^LongWord;
PWordBool = ^WordBool;
PUnknown = ^IUnknown;
PPUnknown = ^PUnknown;
PByte = ^Byte;
PPWideChar = ^PWideChar;
Snap (2002-12-15 23:34:00) [35]Лучше всего природу Pchara понять поможет его объявление - ^char.
Sha (2002-12-15 23:33:00) [36]Иногда, например, бывает надо обработать целочисленный массив побайтно - PChar незаменим.
Snap (2002-12-15 23:20:00) [37]Насколько я знаю, strPass или StrPCopy делает как раз то что тебе надо!.
Anatoly Podgoretsky (2002-12-15 23:10:00) [38]TTCustomDelphiMaster © (14.12.02 23:32)
PChar можно использовать не только как указатель на ASCIIZ строку, а на что угодно, только работать надо не как со строкой
Иногда это удобно из за поддержки адресной математики, как использование string не для хранения строк, а двоичных данных, из за великолепного управления памятью.
Fantasist (2002-12-15 23:05:00) [39]
> Это только, если PChar указывает на строку, заканчивающуюся
> нулем, что не есть непреложный факт
Если это С-строка не заканчивающаяся нулем, то это уже не строка, а просто указатель на нечто. Чтобы она была строкой (С-строкой), она обязанна заканчиваться на 0.
Набережных С. (2002-12-14 23:37:00) [40]Ну не реально, так не реально. Смыслов много, но это для меня. Настаивать я не буду.