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

Вниз

Pchar(s)^   Найти похожие ветки 

 
Vitec   (2008-04-15 19:18) [0]

подскажите пожалуйста, что означает запись: PChar(S)^
s- типа string PChar(S) - преобразуем строку в тип Pchar, а вот что означает значек ^ в конце?


 
Palladin ©   (2008-04-15 19:22) [1]

разименование указателя, бежим изучать основы паскаля...


 
Семеныч   (2008-04-15 19:25) [2]

По умолчанию S - это длинная строка. То есть, указатель на адрес ее тела (причем тело это заканчивается символом #0).

Тип PChar - это указатель на символ.

Значит, PChar(S) - это адрес первого символа строки S.

А PChar(S)^ - это сам первый символ строки (или символ #0, если строка пустая).


 
Anatoly Podgoretsky ©   (2008-04-15 19:53) [3]

> Vitec  (15.04.2008 19:18:00)  [0]

А зачем такие глупости делать, для работы со строками нет нужды приводить к PChar и далее делать разименование.


 
Vitec   (2008-04-15 20:09) [4]

Palladin,
угу, надо почитать, с указателями не подружился еще, без них обходился
Семеныч,
спасибо за разъяснения
Anatoly Podgoretsky
Пытаюсь разобраться в md5
function MD5String(const S: string): TMD5Digest;
begin
 Result := MD5Buffer(PChar(S)^, Length(S));
end;

нужно для функции MD5Buffer, которая используется для обработки данных разных типов


 
Anatoly Podgoretsky ©   (2008-04-15 20:21) [5]

> Vitec  (15.04.2008 20:09:04)  [4]

Это какой то бессмысленный код, вот если убрать каре, то будет рабочим.


 
Vitec   (2008-04-15 20:27) [6]

код как-раз прекрасно работает:
http://www.delphiworld.narod.ru/base/md5.html
в нем и разбираюсь.


 
Palladin ©   (2008-04-15 20:29) [7]


> Anatoly Podgoretsky ©   (15.04.08 20:21) [5]

это очень хитрый код... у меня доступа нет по http куда нибудь кроме delphimaster"a, но могу предположить, что объявление выглядит так
MD5Buffer(Var p; ...);


 
tesseract ©   (2008-04-15 20:30) [8]


> код как-раз прекрасно работает:


Это поймёт тебя компилятор или нет. Delphi иногда такое прощает.


 
tesseract ©   (2008-04-15 20:33) [9]


> это очень хитрый код... у меня доступа нет по http куда
> нибудь кроме delphimaster"a, но могу предположить, что объявление
> выглядит так


function MD5Buffer(const Buffer; Size: Integer): TMD5Digest;

т.е разименование тут роли сыграть не должно :-).


 
Palladin ©   (2008-04-15 20:34) [10]


> tesseract ©   (15.04.08 20:33) [9]

я так и предполагал const или var, очень даже должно, вместо нарыва на AV при s[1], мы хитро на уровне compiler magic приводим string к pchar и спокойно разименовываем


 
Johnmen ©   (2008-04-15 20:35) [11]


> Семеныч   (15.04.08 19:25) [2]
> По умолчанию S - это длинная строка. То есть, указатель
> на адрес ее тела (причем тело это заканчивается символом
> #0).

Не надо фантазий :)


 
tesseract ©   (2008-04-15 20:42) [12]


>  мы хитро на уровне compiler magic приводим string к pchar
> и спокойно разименовываем


Такие привычки надо ликвидировать, но тут сработает без проблем. "Плавающий AV " - плата за умность компилятора.


 
Vitec   (2008-04-15 21:01) [13]

Тогда еще вопрос, что такое плавающий AV? и почему s[1] может не прокатить?
P.s. про указатели уже почти дочитал :)


 
Игорь Шевченко ©   (2008-04-15 21:18) [14]


> Тогда еще вопрос, что такое плавающий AV?


Сегодня есть, завтра нет.


> почему s[1] может не прокатить?


может и прокатить


 
Vitec   (2008-04-15 21:46) [15]

Всем спасибо! И все же, из-за чего может возникнуть ошибка доступа к памяти при прямом обращении s[1], а не через указатели?


 
Palladin ©   (2008-04-15 21:58) [16]

как показывает практика, из-за специфики работы вызываемой функции, а точнее аффторов, ее писавших... которые были на столько чудаками на букву м, что проверяли корректность переданной длинны ASCIIZ... волшебники, мля...


 
tesseract ©   (2008-04-15 22:19) [17]


> волшебники, мля...


"И прям,  не волшебники" (С) Жмурки  

Из за специфики работы с памятью. Столько с GlobalAlloc натерпелся....


 
Игорь Шевченко ©   (2008-04-15 22:29) [18]

function MD5DigestCompare(const Digest1, Digest2: TMD5Digest): Boolean;
begin
 Result := False;
 if Digest1.A <> Digest2.A then
   Exit;
 if Digest1.B <> Digest2.B then
   Exit;
 if Digest1.C <> Digest2.C then
   Exit;
 if Digest1.D <> Digest2.D then
   Exit;
 Result := True;
end;

менять на

function MD5DigestCompare(const Digest1, Digest2: TMD5Digest): Boolean;
begin
 Result := (Digest1.A = Digest2.A) and (Digest1.B = Digest2.B) and (Digest1.C = Digest2.C) and (Digest1.D = Digest2.D);
end;


 
palva ©   (2008-04-15 22:37) [19]


> И все же, из-за чего может возникнуть ошибка доступа к памяти
> при прямом обращении s[1], а не через указатели?

Из-за того что нельзя обращаться к символам пустой строки. Обычно это приводит к чтению по нулевому адресу - так уж устроены строки.

{$APPTYPE CONSOLE}
var
 s: String;
 i: Integer absolute s;
begin
 s := "";
 WriteLn(Integer(PChar(s))); // 4207937
 // Здесь был выделен буфер, и туда скопирована пустая строка с завершающим нулевым байтом.
 WriteLn(Ord(PChar(s)^));    // 0
 WriteLn(i);         // 0
 WriteLn(Ord(s[1])); // попытка чтения по адресу ноль
end.


 
tesseract ©   (2008-04-15 22:50) [20]


>  Обычно это приводит к чтению по нулевому адресу - так уж
> устроены строки.


Хорошо, если,  по нулевому, иногда приводит к записи в реальную кучу. И  "плавающий AV" в подарок.


 
palva ©   (2008-04-15 22:56) [21]


> Хорошо, если,  по нулевому, иногда приводит к записи в реальную
> кучу.

На это моей фантазии не хватило.


 
Семеныч   (2008-04-16 00:27) [22]


> Johnmen ©   (15.04.08 20:35) [11]
>
> > Семеныч   (15.04.08 19:25) [2]
> > По умолчанию S - это длинная строка. То есть, указатель
> > на адрес ее тела (причем тело это заканчивается символом #0).
>
> Не надо фантазий :)


Заявление, потрясающее как своей информативностью, так и своей обоснованностью. Впрочем, здесь такое не редкость, как я успел убедиться. Увы.

Однако же, есть вот такой код

procedure TForm1.FormCreate(Sender: TObject);
var
 Source, Target: string;
 P: Pointer;
 i: integer;
begin
 Source := "qwerty";
 P := Pointer(Source);
 Target := "";
 for i := 1 to Length(Source) do
 begin
   Target := Target + PChar(P)^;
   P := Pointer(Cardinal(P) + 1);
 end;
 Caption := Target;
 P := Pointer(Cardinal(P) + 1);
 Caption := Format("%s #%d", [Target, Ord(PChar(P)^)]);
end;

Что мы видим из этого кода?
1. Что по умолчанию S - это длинная строка.
2. Что S есть указатель на адрес собственного тела.
3. Что тело это заканчивается символом #0.

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

Уважаемый синештаноноситель! Я, конечно, понимаю, что пояснения и доказательства - дело не царское, но все же: не могли бы Вы все это хоть как-то прокомментировать?

Конечно, хотелось бы комментариев вразумительных. А не в том же духе.


 
Vitec   (2008-04-16 09:00) [23]

теперь понятно, прочитал заодно про ASCIIZ в википедии и какие с ним обычно бывают ошибки, а также из-за чего возникают Access Violation
всем еще раз спасибо за разъяснения!


 
Семеныч   (2008-04-16 09:16) [24]


> Johnmen ©   (15.04.08 20:35) [11]


Дополнение к [22]. Про азбуку (счетчик ссылок и размер в памяти) затрудняться не стоит. Надо сказать, что именно в цитате есть фантазия и почему. Ждем-с.


 
Leonid Troyanovsky ©   (2008-04-16 09:30) [25]


> Семеныч   (16.04.08 00:27) [22]

> 1. Что по умолчанию S - это длинная строка.
> 2. Что S есть указатель на адрес собственного тела.
> 3. Что тело это заканчивается символом #0.

Под умолчанием, видимо, подразумевается $H+.

А вот с телом не совсем точно. Разница проявляется
именно в пустой строке: указатель есть nil, и никакой
памяти для нее не распределено, т.е. он не указывает на #0,
в отличии от PChar("").

Ну, и точнее говорить не на "тело", а на распределенный
для строки блок, начинающийся с 12 байтового заголовка
по отрицательному смещению.

Все это доступно изложено в хелпе, которому и следует,
IMHO, в подобных случаях отсылать страждущих.

--
Regards, LVT.


 
Семеныч   (2008-04-16 10:22) [26]

> Leonid Troyanovsky ©   (16.04.08 09:30) [25]

>> 1. Что по умолчанию S - это длинная строка.
>> 2. Что S есть указатель на адрес собственного тела.
>> 3. Что тело это заканчивается символом #0.

> Под умолчанием, видимо, подразумевается $H+.

Естественно.

> А вот с телом не совсем точно. Разница проявляется
> именно в пустой строке: указатель есть nil, и никакой
> памяти для нее не распределено

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

О пустой строке я сказал лишь то (см. [2]), что PChar(S)^ - это "символ #0, если строка пустая". И это тоже абсолютно верно.

> Ну, и точнее говорить не на "тело", а на распределенный для строки блок,
> начинающийся с 12 байтового заголовка по отрицательному смещению.

Насколько помню, заголовок - это все же 8 байт (4 - счетчик ссылок и 4 - размер). Ну да ладно, суть не в этом.

Суть в том, что заголовок находится именно по отрицательному смещению, поэтому сам указатель содержит адрес именно первого символа строки и никакой другой. А это и есть адрес тела строки. Как видим, и здесь все абсолютно точно.

И, наконец: если уж что-то кому-то показалось неточным или неправильным, то надо было, видимо, написать, что именно и почему (как это сделали Вы - а то, что я с Вами не согласился, это уже другой вопрос и это тоже нормально).

Но почему же вместо этого здесь принято бросаться снисходительными и голословными поучениями?


 
Leonid Troyanovsky ©   (2008-04-16 13:26) [27]


> Семеныч   (16.04.08 10:22) [26]

> Насколько помню, заголовок - это все же 8 байт (4 - счетчик
> ссылок и 4 - размер). Ну да ладно, суть не в этом.

Ну, да. Это раньше еще был  allocSiz: Longint, sorry.

> То есть, все три абсолютно верны.

Я ж показал, что не абсолютно.
Т.е., для полноты не хватает именно пустой строки.

Кста потому,  PChar(S)^ - это "символ #0, если строка пустая",
(т.е. бестелесная), а Pointer(s) = nil - перечитай еще раз тезисы 2, 3.

--
Regards, LVT.


 
Johnmen ©   (2008-04-16 13:41) [28]


> Семеныч   (16.04.08 00:27) [22]
> Семеныч   (16.04.08 09:16) [24]
> Семеныч   (16.04.08 10:22) [26]

Кипит наш разум возмущенный (с) ?
Я думаю, к данному моменту уже успокоился...

Так вот.
Если ты начинаешь применять отформализованную демагогию и понятие абсолюта, то я, в этом же духе, на
> Но заметьте, что о пустой строке в приведенных выше пресловутых трех
> пунктах искомой цитаты нет ни одного звука.

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

Вот такие дела...


 
Anatoly Podgoretsky ©   (2008-04-16 15:14) [29]

> Leonid Troyanovsky  (16.04.2008 13:26:27)  [27]

И при этом

> PChar(S)^ - это "символ #0, если строка пустая",

РеадОнли память, в сегменте констант, на это часто прокалываются, например с OemToChar(PChar(S), PChar(S))


 
Семеныч   (2008-04-16 15:56) [30]

> Johnmen ©   (16.04.08 13:41) [28]

1. Насчет формализованной демагогии - см. [11].

2. Вы не ответили на вопрос (последний абзац в [26]). Умышленно?


 
Johnmen ©   (2008-04-16 16:54) [31]


> Семеныч   (16.04.08 15:56) [30]
> 2. Вы не ответили на вопрос (последний абзац в [26]). Умышленно?

Да, умышленно. Ибо он для меня риторический.
Если для тебя он иной, то отвечаю:
Наверняка - не знаю, а о предположениях умолчу. Умышленно.


 
Семеныч   (2008-04-16 17:25) [32]

> Johnmen ©   (16.04.08 16:54) [31]

Тогда с себя и начни. Умышленно.


 
Johnmen ©   (2008-04-16 19:12) [33]


> Семеныч   (16.04.08 17:25) [32]
> Тогда с себя и начни. Умышленно.

Что конкретно мне начать с себя?



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

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

Наверх




Память: 0.56 MB
Время: 0.021 c
2-1208719740
worldmen
2008-04-20 23:29
2008.05.18
Загрузить с ini файла в переменную имена всех ключей


2-1208758852
Vudu
2008-04-21 10:20
2008.05.18
Как преобразовать char в integer


15-1207236481
Дмитрий С
2008-04-03 19:28
2008.05.18
Хостинг


8-1179768333
NewZ
2007-05-21 21:25
2008.05.18
*.wav файлы!!!


2-1208846129
switch
2008-04-22 10:35
2008.05.18
Работа с БД Access