Форум: "Начинающим";
Текущий архив: 2007.07.08;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.082 c