Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

FillChar для строки [D7, XP]


Страницы:   1 2 3

Dmitry_177 ©   (2007-05-26 02:25:00) 

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

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

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

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

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

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


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

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


Anatoly Podgoretsky   (2007-05-26 14:45:00) [22]

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

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


Loginov Dmitry   (2007-05-26 14:27:00) [23]

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


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


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

просто на сколько я знаю "#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;


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


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

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


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


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


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

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

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


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

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

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

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


Loginov Dmitry   (2007-05-26 13:43:00) [27]

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


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


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


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

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

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


Riply   (2007-05-26 12:12:00) [29]

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


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


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


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


Loginov Dmitry   (2007-05-26 10:11:00) [31]

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


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


palva   (2007-05-26 09:58:00) [32]

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


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

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


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


> 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 будет...

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


Loginov Dmitry   (2007-05-26 09:31:00) [35]

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


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


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


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

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


Loginov Dmitry   (2007-05-26 09:23:00) [37]

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


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


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


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


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


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


> 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 - пустячок, а приятно...


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

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


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо