Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.07.08;
Скачать: CL | DM;

Вниз

FillChar для строки   Найти похожие ветки 

 
Dmitry_177   (2007-05-26 02:25) [0]

Как правильно выполнить FillChar для строки?

Если выполнить так:

var
s: string;
...
FillChar(s, SizeOf(s), #0);

ИМХО очистится не сама строка, а указатель на нее..

Вот так правильно ли будет?

var
s: string;
...
FillChar(PChar(s)^, Length(s), #0);


 
Германн ©   (2007-05-26 02:39) [1]

А зачем нужен FillChar для строки?


 
Dmitry_177   (2007-05-26 02:41) [2]

чтоб очистить ее =)


 
Германн ©   (2007-05-26 02:51) [3]


> Dmitry_177   (26.05.07 02:41) [2]
>
> чтоб очистить ее =)
>

От чего очистить?


 
Dmitry_177   (2007-05-26 02:57) [4]

от всякого мусора..


 
Германн ©   (2007-05-26 02:59) [5]


> Dmitry_177   (26.05.07 02:57) [4]
>
> от всякого мусора..
>

Ну а смысл, то в чём?


 
Andy BitOff ©   (2007-05-26 03:14) [6]

Чтобы очистить s:=""; а чтобы заполнить StringOfChar


 
Kedge ©   (2007-05-26 03:43) [7]

> [6] Andy BitOff ©   (26.05.07 03:14)
> Чтобы очистить s:=""; а чтобы заполнить StringOfChar
Довольно "емкие" операции.
Допустим, я в строку, заранее определенной длины MAX_MY_VALUE_LEN, в цикле записываю значения:
for i := 0 to Count do
begin
 // здесь надо очистить строку, IMHO, лучше использовать FillChar
 SomeFunction(MyStr[1], MAX_MY_VALUE_LEN);
 if Pos("bla-bla", MyStr) > 0 then ....
end;


 
Andy BitOff ©   (2007-05-26 04:19) [8]

Да. К сожалению я забыл написать P.S.
Так вот.

Чтобы очистить s:=""; а чтобы заполнить StringOfChar

P.S. Я знаю, что земля не шар.


 
palva ©   (2007-05-26 07:57) [9]


> Вот так правильно ли будет?
>
> var
> s: string;
> ...
> FillChar(PChar(s)^, Length(s), #0);

Так будет правильно. Но нарушится механизм подсчета ссылок. Пример.
{$APPTYPE CONSOLE}
var
 s1, s2: String;
begin
 s1 := "qwerty";
 s2 := s1;
 writeln(s2); // "qwerty"
 FillChar(PChar(s1)^, Length(s1), #0);
 writeln(s2); // выдаст пустую строку
end.

Если вы хорошо понимаете, что произойдет, и ваш текст не будут сопровождать другие программисты, тогда делайте.


 
Loginov Dmitry ©   (2007-05-26 08:59) [10]

> Так будет правильно. Но нарушится механизм подсчета ссылок


Вот он-то как-раз сработает, как и должен. Насколько результат ожидаем - зависит от квалификации того, кто применит данный код.

P.S. А что, константы в консольной проге разве не хранятся в области кода? (Или данные в области кода разрешено модифицировать?)


 
palva ©   (2007-05-26 09:11) [11]

Loginov Dmitry ©   (26.05.07 08:59) [10]
Это я не в курсе. Я написал пример, который демонстрирует, как я предполагаю, неожиданные для автора последствия.


 
Однокамушкин   (2007-05-26 09:18) [12]


> FillChar(PChar(s)^, Length(s), #0);


В этой строке приведение к PChar неправильно... Правильнее приводить к Pointer, потому что PChar(string) на самом деле не приведение типов, а неявный вызов функции _LStrToPChar. Если s<>"", то Pointer(s)=PChar(s), а вот если s="", то Pointer(s)=nil, а PChar(s)<>nil, он указывает на символ #0, размещённый в сегменте кода... Тут конечно без разницы, какой будет указатель, если длина всё равно ноль, но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...


 
Однокамушкин   (2007-05-26 09:21) [13]


> palva ©   (26.05.07 09:11) [11]
> Loginov Dmitry ©   (26.05.07 08:59) [10]
> Это я не в курсе. Я написал пример, который демонстрирует,
>  как я предполагаю, неожиданные для автора последствия.


Неожиданным последствием в данном случае будет access violation, т.к. вы пытаетесь модифицировать сегмент кода...


 
Loginov Dmitry ©   (2007-05-26 09:23) [14]

> Неожиданным последствием в данном случае будет access violation,
> т.к. вы пытаетесь модифицировать сегмент кода...


[10] читать будем?


 
Однокамушкин   (2007-05-26 09:27) [15]


> Loginov Dmitry ©   (26.05.07 09:23) [14]
>
> [10] читать будем?

Читал, просто решил сказать то же самое немного другими словами, раз palva не согласился сразу и стал возражать... В чём проблема-то?


 
Loginov Dmitry ©   (2007-05-26 09:31) [16]

> Читал, просто решил сказать то же самое немного другими
> словами


Дак я ж про то говорю, что в консольном приложеним "в данном случае" AV-то как раз и не будет.


 
Однокамушкин   (2007-05-26 09:42) [17]


> Loginov Dmitry ©   (26.05.07 09:31) [16]
>
> Дак я ж про то говорю, что в консольном приложеним "в данном
> случае" AV-то как раз и не будет.


Кажись, разобрался... Тут не в консольном приложении дело, а в том, что переменные глобальные... Например, такой код даёт av:

{$APPTYPE CONSOLE}
procedure Test;
var
s1, s2: String;
begin
s1 := "qwerty";
s2 := s1;
writeln(s2); // "qwerty"
FillChar(PChar(s1)^, Length(s1), #0);
writeln(s2);
readln
end;

begin
Test
end.


В неконосльном приложении такой код тоже не даёт ошибки

var s1, s2:string;

procedure TForm1.Button1Click(Sender: TObject);
begin
s1 := "qwerty";
s2 := s1;
FillChar(PChar(s1)^, Length(s1), #0);
Button1.Caption:=s2
end;


Но если сделать переменные локальными, av будет...

Смутно припоминаю, что когда-то видел статью, где об этом говорилось... сейчас попробую найти...


 
Однокамушкин   (2007-05-26 09:45) [18]

Вот, нашёл...
http://www.rsdn.ru/article/Delphi/dynarrays.xml#ENF


 
palva ©   (2007-05-26 09:58) [19]

Однокамушкин   (26.05.07 09:18) [12]
> но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...
Согласен.
Я в таких случаях вообще обхожусь без приведения
FillChar(s[0], Length(s), #0);
и Length(s) я бы не использовал, поскольку наверняка имеется переменная, где эта длина записана.


 
Loginov Dmitry ©   (2007-05-26 10:11) [20]

> Вот, нашёл...


thanks! Буду знать!


 
Однокамушкин   (2007-05-26 10:43) [21]


> palva ©   (26.05.07 09:58) [19]
> Я в таких случаях вообще обхожусь без приведения
> FillChar(s[0], Length(s), #0);


Видимо, имелся ввиду s[1]... Но это тоже корректно только если s<>"", а то будет то же av... а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString, чтобы не повредились переменные, ссылающиеся на ту же строку, а это тоже дополнительная работа для процессора...


 
Riply ©   (2007-05-26 12:12) [22]

> [21] Однокамушкин   (26.05.07 10:43)
> а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString
Вот тебе и раз :(
А как тогда можно "побыстрее" очистить строку ?
Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива :)


 
Однокамушкин   (2007-05-26 12:53) [23]


> Riply ©   (26.05.07 12:12) [22]
> А как тогда можно "побыстрее" очистить строку ?

А так, как мы уже тут говорили...
FillChar(Pointer(s), cbStrLen, #0)

Быстрее, наверное, только на асемблере...


 
Loginov Dmitry ©   (2007-05-26 13:43) [24]

> А как тогда можно "побыстрее" очистить строку ?
> Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива
> :)


Очищай так и далее, и будь счастлива. Тем более, что не вижу практического смысла применения операции FillChar к строкам (ну ни разу практически не вознакала такая потребность)


 
Dmitry_177   (2007-05-26 13:51) [25]

а если к примеру есть строка, и мы не знает есть ли в ней что-то или она пустая.. как тогда лучше делать? Ведь как тут уже говорилось Pointer(str) при пустой строке вернет nil. Вот так?

if str <> "" then
 FillChar(Pointer(str), Length(str), #0);


А еще если Length-ем не вариант пользоваться, то чем тогда лучше?

> и Length(s) я бы не использовал, поскольку наверняка имеется
> переменная, где эта длина записана.

У меня нету такой переменной..

А еще что лучше передавать третьим параметром? ведь если передавать "#0" и "0" строка в обоих случаях очищается..


 
Однокамушкин   (2007-05-26 14:01) [26]


> Ведь как тут уже говорилось Pointer(str) при пустой строке
> вернет nil.

Но ведь вот какая штука: Length(str) при ёэтом вернёт 0... А FillChar, он достаточно умный, чтобы при нулевой длине не обращаться к памяти, на которую указывает первый параметр... Так что ничего страшного, отдельно s<>"" можно не проверять...


> А еще что лучше передавать третьим параметром? ведь если
> передавать "#0" и "0" строка в обоих случаях очищается..


А без разницы... Для процессора что то - ноль, что это - ноль...


 
Dmitry_177   (2007-05-26 14:24) [27]

просто на сколько я знаю "#0"-это именно нулевой символ, а "0" - это символ 48.. Может какое-то да тратится время на перевод из 0 в #0? Вот я и спросил может сразу уж "#0" задавать..

Но если так у меня встречный вопрос, а если мы очищаем не строку а какую-то структуру? Где есть и строки и числа? тут уже что лучше "#0" или "0"?

Кстати как лучше структуры очищать? Что передавать первым и вторым параметром? Вот к примеру есть такая структура:

 Tabc = packet record
   a: integer;
   b: integer;
   c: string или pchar или array [0..MAX_PATH-1] of Char;
 end;


Что лучше передавать в Fillchar первым параметром? abc или Pointer(abc)?

P.S. насчет параметра c, незнаю как string и pchar, я использую array [0..MAX_PATH-1] of Char;


 
Loginov Dmitry ©   (2007-05-26 14:27) [28]

> просто на сколько я знаю "#0"-это именно нулевой символ,
> а "0" - это символ 48


Ноль - он и в африке ноль!


 
Anatoly Podgoretsky ©   (2007-05-26 14:45) [29]

> Loginov Dmitry  (26.05.2007 14:27:28)  [28]

Использовать FillChar самому себе вредить, а потом удивляемся откуда знаменитый buffer overflow
Насколько я помню в .NET компилятор грубо обругает за подобные вольности.


 
Dmitry_177   (2007-05-26 14:48) [30]

Anatoly Podgoretsky, ладно бог с ней с этой строкой.. а как тогда структуру очищать без FillChar-а?


 
Loginov Dmitry ©   (2007-05-26 15:05) [31]

ZeroMemory :)


 
palva ©   (2007-05-26 15:08) [32]


> Однокамушкин   (26.05.07 12:53) [23]
> А так, как мы уже тут говорили...
> FillChar(Pointer(s), cbStrLen, #0)

Теперь всегда так буду делать. Конечно, если мне когда нибудь взбредет в голову вспомнить детство и позаниматься извращениями.


 
Anatoly Podgoretsky ©   (2007-05-26 15:11) [33]

> Loginov Dmitry  (26.05.2007 15:05:31)  [31]

Шило на мыло


 
Dmitry_177   (2007-05-26 15:13) [34]

Loginov Dmitry,  в ZeroMemory ее коде FillChar, посмотри..


 
Однокамушкин   (2007-05-26 15:46) [35]


> просто на сколько я знаю "#0"-это именно нулевой символ,
>  а "0" - это символ 48..

0 и "0" - это разные вещи... 0 соответствует #0, а "0" - #48...


 
Dmitry_177   (2007-05-26 16:36) [36]

Кстати если так подумать то ведь я не только в FillChar передавал PChar(str), но и во все API функции.. Тогда лучше в них Pointer(str) передавать?


 
Dmitry_177   (2007-05-26 16:41) [37]

Да и еще, при: FillChar(Pointer(str), Length(str), #0); при последующей работе с str выскакивает AV, а так: FillChar(Pointer(str)^, Length(str), #0);


 
Dmitry_177   (2007-05-26 16:42) [38]

т.е. с "^" на конце..


 
Loginov Dmitry ©   (2007-05-26 16:55) [39]

> Кстати если так подумать то ведь я не только в FillChar
> передавал PChar(str), но и во все API функции.. Тогда лучше
> в них Pointer(str) передавать?


Вряд ли это че-то будет лучше, не говоря уж о том, что многие API-функции Windows работают в Unicode-формате, и тама расходы на преобразование в UNICODE и обратно куда больше, чем расходы при использовании PChar.


 
begin...end ©   (2007-05-26 17:19) [40]

> Однокамушкин   (26.05.07 10:43) [21]

> Видимо, имелся ввиду s[1]... Но это тоже корректно только
> если s<>"", а то будет то же av...

AV не будет. Может быть только Range Check Error -- если, конечно, включена опция Range Checking.



Страницы: 1 2 вся ветка

Текущий архив: 2007.07.08;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.029 c
15-1181021872
sergeyst
2007-06-05 09:37
2007.07.08
Куда делись компоненты?


2-1181835730
SerMaxx
2007-06-14 19:42
2007.07.08
Работа с Exel из Delphi


15-1181497626
default
2007-06-10 21:47
2007.07.08
Гостиница в москве


11-1163962193
Vladimir Kladov
2006-11-19 21:49
2007.07.08
Версия 2.43


15-1181287515
balepa
2007-06-08 11:25
2007.07.08
Че то на RSDN зайти не могу