размер строк pChar в паскале

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

размер строк pChar в паскале

Сообщение sacred phoenix » 11.05.2007 15:52:26

Если объявить константу или переменную типа pChar, то как проще всего обратиться к ее длине? sizeof возвращает 4 - разиер указателя. Можно использовать что-нибудь вроде lstrlen, но это некрасиво и медленно. Можно конечно объявлять строку как ansistring(она тоже заканчивается нулем, как и pChar) и длину брать как length(ansistring), но это уже немного не то.
sacred phoenix
незнакомец
 
Сообщения: 7
Зарегистрирован: 12.04.2007 19:20:08

Сообщение shade » 11.05.2007 16:23:29

Length применима и к pchar
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение Replicator » 11.05.2007 16:29:14

По-моему, самый быстрый, но не самый лучший способ - WinAPI. Если надо соблюсти кроссплатформенность, то используй что-то вроде lstrlen/length...

Там проблема в том, что единственный способ узнать фактическую длину строки - найти в этой строке символ #0, а как это сделать, если не перебором?

А вообще, ansistring, на мой взгляд, оптимальный вариант. Вычисление длины происходит практически без затрат, так как длина строки хранится по смещению -4 от адреса в указателе (по крайней мере в Delphi). А приведение типа туда-обратно происходит также очень быстро - все что надо, это "забыть" о смещении -4 и добавить в конец (адрес известен) #0, если его там нет (а если, как Вы говорите, там уже есть #0, то и этого не надо).
Replicator
постоялец
 
Сообщения: 154
Зарегистрирован: 30.04.2006 17:14:45
Откуда: Outer Heaven

Сообщение sacred phoenix » 11.05.2007 17:29:01

length для переменной типа pChar компилируется в тот же поиск нулевого байта в конце(у меня FPC 2.0.4), а для типа ansistring это взятие значения на по смещению -4 относительно указателя на строку, что конечно намного быстрее. Я согласен, что это самый оптимальный путь.
Я посмотрел на приведение типов в FPC, если использовать приведение к pChar компилятор вставляет дополнительную проверку на содержание нуля в переменной; приведение к pointer этого не дает, т.е. это будет немного оптимальнее.
sacred phoenix
незнакомец
 
Сообщения: 7
Зарегистрирован: 12.04.2007 19:20:08

Сообщение shade » 11.05.2007 18:04:26

Replicator писал(а):А приведение типа туда-обратно происходит также очень быстро - все что надо, это "забыть" о смещении -4 и добавить в конец (адрес известен) #0, если его там нет (а если, как Вы говорите, там уже есть #0, то и этого не надо).

В fpc, да и в delphi, данное приведение реализуется несколько сложнее.
Если счетчик ссылок не равен 1, то строка дублируется (т.е. выделяется память под новую строку, затем копируются символы), а затем уж забывается, что там есть длина и счетчик ссылок.

PS: нуль в конце есть ansistring поумолчанию
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение Sergei I. Gorelkin » 11.05.2007 21:01:12

sacred phoenix писал(а): Я посмотрел на приведение типов в FPC, если использовать приведение к pChar компилятор вставляет дополнительную проверку на содержание нуля в переменной; приведение к pointer этого не дает, т.е. это будет немного оптимальнее.

Зато может рухнуть, если на вход попадется пустая строка. Пустая строка - это nil, приведение ее к PChar даст ненулевой указатель на нулевой байт, а приведение к Pointer даст nil.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение shade » 11.05.2007 22:42:03

Не рухнет, т.к. в если строка пустая, то дается указатель на символ с кодом 0.

PS: Странно, я думал что length(nil) должна работать и возвращать 0... а она оказывается рушиться, помоему это можно считать багом..
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение STAKANOV » 12.05.2007 00:33:57

shade писал(а):PS: Странно, я думал что length(nil) должна работать и возвращать 0... а она оказывается рушиться, помоему это можно считать багом.

length не предназначен для работы с PChar, для PChar предназначена strlen из модуля strings
Последний раз редактировалось STAKANOV 12.05.2007 00:37:55, всего редактировалось 3 раз(а).
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение sacred phoenix » 12.05.2007 09:54:45

В С например можно так:
char s[]="string";
и sizeof(s) теперь значит число, полностью длину строки с нулем в конце.
В паскале похоже придется использовать ansistring, а это не так удобно, т.к. чтобы взять длину приходится читать из памяти. И, например, если писать без RTL, то ansistring неприменима :(
Неужели без поиска нулевого байта остается только вручную посчитать длину строки-константы?
sacred phoenix
незнакомец
 
Сообщения: 7
Зарегистрирован: 12.04.2007 19:20:08

Сообщение shade » 12.05.2007 12:46:52

sacred phoenix писал(а):В С например можно так:
char s[]="string";

В данном случае имеем массив
Например в случае
char s[] = "str\0ing";
strlen(s) != sizeof(s)
да и sizeof(s) даст длину с учетом нуль символа (т.е. на 1 больше чем strlen), если я че не путаю..

В паскале тоже можно
var s: array [0..8] of char = 'string';
len := sizeof(s);

STAKANOV писал(а):length не предназначен для работы с PChar,

Но тем не менее работает, см fpc_pchar_length, который отвечает за legth(p: pchar)
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение STAKANOV » 12.05.2007 14:33:56

shade писал(а):STAKANOV писал(а):length не предназначен для работы с PChar,

Но тем не менее работает, см fpc_pchar_length, который отвечает за legth(p: pchar)

верно, документация видно немного остает :cry:

Вот еще немного рискованный вариант:
Код: Выделить всё
const s:PChar='12346789';
const s_end:PChar='#';
var
  ss:LongWord;
begin
  ss:=s_end-s;
  writeln(ss);
end.


Правда гарантии, что компилятор расположит в памяти две констаный друг за другом нет никакой. :cry:
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение sacred phoenix » 12.05.2007 18:55:49

В паскале тоже можно
var s: array [0..8] of char = 'string';
len := sizeof(s);


но тем не менее довольно неудобно вручную пересчитывать символы в строке...хотя выходит что это лучше всего.

да и sizeof(s) даст длину с учетом нуль символа (т.е. на 1 больше чем strlen), если я че не путаю..


Да он считает и нулевой символ в конце, но если допустим использовать sizeof(s)-1 то любой компилятор увидит, что тут тоже просто число. Ну а если считать такую строку-массив константой(а такие тоже нужны часто) и не изменять ее то там никогда в середине не появится \0.

Вот еще немного рискованный вариант:


Рискованный вариант наверно будет самый удачный если писать без RTL и если учитывать то, что он рискованный
sacred phoenix
незнакомец
 
Сообщения: 7
Зарегистрирован: 12.04.2007 19:20:08

Сообщение STAKANOV » 12.05.2007 20:00:37

sacred phoenix писал(а):если писать без RTL

кстати, как-то обсуждалось:
http://freepascal.ru/forum/viewtopic.php?t=453

извините за оффтопик :oops:
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение shade » 12.05.2007 20:45:55

Можно сделать так :wink:
Код: Выделить всё
type
  mystr = record
    len: integer;
    str: pchar;
  end;
const
  S = 'string';
  x: mystr = (len: length(S); str: S);
begin
  writeln('Len: ', x.len);
  writeln(x.str);
end.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение shade » 12.05.2007 21:13:40

Что-то я совсем заработался..

Если у вас объявлена константа pStr:pchar, то length(pStr) компилятор вычислит как константу (см. в подтверждение выше), так что это единственно верный способ узнать длину константной строки на этапе компиляции.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru