Форум: "Основная";
Текущий архив: 2003.04.24;
Скачать: [xml.tar.bz2];
ВнизПроблема с PChar Найти похожие ветки
← →
Giemgo (2003-04-11 21:53) [0]Вот мой код:
procedure TForm1.Button1Click(Sender: TObject);
var P:PChar;
begin
P:="Hello";
showmessage(P); //Здесь стоит брекпойнт
end;
По брекпоинту в окне CPU перехожу по адресу переменной P - вижу там полную фигню. Почему ?
← →
Giemgo (2003-04-11 21:57) [1]Как понимаю, при
P:="Hello"
компилятор выделяет 5 байт под слово и записывает его в память. @P указывает на первый символ.
В CPU windows символ на который указывает P вовсе не "H" и последующие вовсе не "ello"
← →
Palladin (2003-04-11 21:58) [2]а что ты там ожидал увидеть?
строку чтоли...
под указатель надо память выделять... этому тебя в школе не учили?
← →
Giemgo (2003-04-11 22:11) [3]Как понимаю, при P:="Hello" компилятор выделяет 5 байт под слово и записывает его в память
← →
Sha (2003-04-11 22:13) [4]2Giemgo (11.04.03 22:11)
неправильно понимаешь.
← →
Palladin (2003-04-11 22:18) [5]
> Giemgo (11.04.03 22:11)
хахаха
откуда пришло к тебе это понимание?
странно даже както...
на всякий случай
конвертация string в pchar
var
s:string;
p:pchar;
s:="Hello";
p:=PChar(s);
← →
Giemgo (2003-04-11 22:25) [6]Palladin, хорошо. Тогда если я неправ, почему
showmessage(P);
все таки выводит "Hello", а не мусор ?
← →
Palladin (2003-04-11 22:43) [7]круто...
P:="Hello";
0044DBAC B8C8DB4400 mov eax,$0044dbc8
вывод
"Hello" в сегменте данных и в P устанавливается ссылка на него,
для строковых констант присваивание будет работать...
для строковых переменных нет...
и кстати ты не прав по поводу "вижу там полную фигню"
я нормальный Hello увидел...
← →
Palladin (2003-04-11 22:49) [8]тьфу
ночь, глючу уже
вот это считать глупостью и не читать...
> для строковых констант присваивание будет работать...
> для строковых переменных нет...
в P устанавливается адрес строки "Hello"
память для P не выделяется...
если ты заведешь P1 такуюже, то строка не скопируется и P и P1 будут указывать на одно и тоже место...
← →
Palladin (2003-04-11 22:53) [9]опять сглючил...
в общем память для PChar именно не выделяется это точно...
хватит с меня... ушел спать..
← →
Giemgo (2003-04-11 23:09) [10]Я что-то запутался:
а что ты там ожидал увидеть?
строку чтоли...
и потом:
и кстати ты не прав по поводу "вижу там полную фигню"
я нормальный Hello увидел...
Я неправильно написал - не в том смысле, что память выделяется, а сама строка как константа пишется, потом P начинает указывать на начало этой строки. Это по идее.
Но как я говорил у меня проблема.
Давайте подробнее:
остановка по брекпоинтуshowmessage(P);
Открываю WatchList, узнаю адрес переменой P
Открываю окно CPU windows, там внизу в левом окне в сплывающем меню нажимаю Goto address. Ввожу узнанный мною адес P
Вижу полную фигню, а не Hello
Вопрос кстати родился от того, что ища ошибку в моей программе по работе с сокетами встретил такую фигню, дальше как бы отлаживать не могу - надо разобраться
← →
Anatoly Podgoretsky (2003-04-12 00:09) [11]Не видать никакой необходимости в использовании PChar вместо string
← →
Fantasist. (2003-04-12 01:09) [12]
> Открываю WatchList, узнаю адрес переменой P
По адресу переменной P, лежит сама переменная P, как это не покажется вам странным. А строка лежит по адресу, который записан в переменной P. Память, в данном случае, выделяется в сегменте памяти, а в P просто записывается адрес этой выделенной памяти.
← →
Giemgo (2003-04-12 09:33) [13]Fantasist, блин, как же я сам не догадался. Спасибо!
Только вот все равно не получается :(
Смотрю, указывает переменая P на байт FC, затем идут F6 12 00
Перехожу в памяти по адресу $FC F6 12 00 - опять фигня :(((
← →
anbezr (2003-04-12 10:45) [14]а ты поставь точку останова не begin, и когда сработает вызови CPU window - сразу все поймешь. проблема в том, что глобальные константы, коей является "Hello", и локальные, коей является P адресуются по разному: первые через DS:EBX, а вторые через смещение в SS:ESP.
← →
anbezr (2003-04-12 10:52) [15]пардон, не правильно подобрал темин, хотя суть это не меняет. не глобальные константы, а константы,описанные вне функции.
← →
Giemgo (2003-04-12 12:00) [16]Плохо понимаю, при чем тут вообще смещения ?
Я же нахожу не по смещению относительно сегмента данных, а по адресу переменной.
И если остановить на begin, то P еще будет не инициализирована
Так... во время написания потыркался и, блин, понял, что туплю по страшному. Ведь указатель - это 4-х байтовое целое, соответственно, указатель указывает на младший байт в адресе строки :)
В общем, он указывал на $FC F6 12 00, а сам то адрес в памяти значит $00 12 F6 FC
← →
anbezr (2003-04-12 12:24) [17]ну так что, получилось? увидел строчку по [p]
← →
Giemgo (2003-04-12 16:46) [18]Не знаю что такое [p], но строчку увидел, когда обратился по адресу записанном в байтах, на которые указывает P. В общем, как сказал Fantasist.
← →
Giemgo (2003-04-12 20:07) [19]Anatoly Podgoretsky
" Не видать никакой необходимости в использовании PChar вместо string"
Вы так считаете ? А если нужно передать в функцию по ссылке PChar ? Как например для функции sendto второй параметр.
Покажите мне как можно использовать string в качестве второго параметра для sendto
← →
Morfein (2003-04-12 20:14) [20]
sendto(..., "строковая константа", ... );
устраивает? :)
можно и по другому...
var
s : string;
begin
s:="строковая переменная";
sendto(..., pointer(s), ... );
← →
Giemgo (2003-04-12 22:53) [21]Morfein, хорошо написал, нда.
sendto(..., "строковая константа", ... );
устраивает? :)
Нет, не устраивает. Ты сам то хоть попробуй так сделать
sendto(..., pointer(s), ... );
И чего ?! И куда интересно указывают байты Hell в hex форме ?
← →
NA (2003-04-12 23:53) [22]
> Giemgo (12.04.03 20:07)
> Anatoly Podgoretsky
> "Не видать никакой необходимости в использовании PChar вместо
> string"
> Вы так считаете ? А если нужно передать в функцию по ссылке
> PChar ? Как например для функции sendto второй параметр.
> Покажите мне как можно использовать string в качестве второго
> параметра для sendto
Согласен с предыдущим оратором совершенно.
PChar (string) - и без проблем. Иногда - @String[1] (когда допустимо).
Я вопщем не против PChar как явления. Но! Вот, скажем, я когда-то себе в назидание сохранил такой кусок кода (из прынцыпу нашел - половину вырезал для облегчения восприятия):
.........
Open := StrAlloc (256); Open := PChar (Dlg_Open.FileName);
Save := StrAlloc (256); Save := PChar (Dlg_Save.FileName);
.........
try CopyFile (Open, Save, false) except
.........
case Dlg_Open.FilterIndex of
1 : Open := PChar (ChangeFileExt (Open, TV_ext));
2 : Open := PChar (ChangeFileExt (Open, TV_bak));
end;
.........
case Dlg_Save.FilterIndex of
1 : Save := PChar (ChangeFileExt (Save, TV_ext));
2 : Save := PChar (ChangeFileExt (Save, TV_bak));
end;
.........
try CopyFile (Open, Save, false) except
Error ("Не удалось скопировать связанный список погрузки")
.........
Так вот, к моменту копирования второго файла в PChar"ах вместо нормальных имен оказывался тааакой бардак, что я с тех пор стараюсь вообще нигде в преобразованиях типов их не использовать. Или сам заглючишь - увлечешься "совместимостью", или компилятор пошутит.
← →
Giemgo (2003-04-13 00:01) [23]Плохо понял вышенаписанное. Я уже указал где я не могу использовать string вместо PChar. Если в данном случае стринг использовать можно - покажите как!
← →
NA (2003-04-13 00:20) [24]Куда уж проще.
← →
Giemgo (2003-04-13 13:20) [25]Что куда уж проще ?
Вы можете ПРИВЕСТИ пример вызова sendto со вторым параметром string,а не PChar ???!! Анатолий Подгорецкий сказал, что нет необходимости использовать PChar, если есть string. Ну а вот я не понимаю, как его здесь можно использовать!
sendto(..., "строковая константа", ... );
даже не откомпилируется. Не знаю о чем думал автор сообщения
sendto(..., pointer(s), ... );
Откомпилируется, конечно. Только вот ЧТО получится...
← →
Anatoly Podgoretsky (2003-04-13 13:33) [26]А назови такое место, где ты не можешь использовать string вместо array[] оf char?
Есть много вариантов использования, например Pointer(S) или Pchar(S), именно так и можешь передавать в любую функцию.
← →
Anatoly Podgoretsky (2003-04-13 13:37) [27]О какой функции sendto ты говоришь, по моему хелпу, второй параметр этой функции Integer
← →
NA (2003-04-13 14:45) [28]
> Giemgo (13.04.03 00:01)
> Плохо понял вышенаписанное.
Вчера перечитывал пейджер... много думал... :)))
1) PChar (string)
2) @string[1]
Если тебе и первый непонятен, второй еще долго не понадобится. Интересно вообще, как ты пишешь что-то там "на чистом API" (это из соседней твоей темы) при таких знаниях.
← →
Giemgo (2003-04-13 15:20) [29]Anatoly Podgoretsky, функция описана в win32sdk.hlp
Объявление есть в модуле winsock
Повторюсь, что второй параметр надо передать по ссылке, то есть:
function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;
tolen: Integer): Integer; stdcall;
PChar(s) не подходит. Pointer(s) фигню выдает. Тем более, я так думаю, так нельзя писать, потому что Ponter(s) вернет указатель на структуру string, которая недокументирована
NA, лично я удивляюсь как ты при своих знаниях находишь смелость что-то советовать другим. Это относится как и к моей соседней ветке, так и к этой. Уважаемый, вы сначала сами попробуйте сделать как написали, а потом уж говорите. Ок ?
← →
Anatoly Podgoretsky (2003-04-13 15:38) [30]А вот другое объявление
function SendTo: (var buf; bufsize: integer; ToAddr: TSockAddr; flags:
Поэтому надо конкретно указывать о каком SendTo идет речь или просто привести объявление функции.
В данном случае, это указатель на абсолютно любой абстрактный буфер, абсолютно любой .
В качестве его может быть статически распреденный, массив, динамический одномерный массив, динамически выделенная память, строка или что нибудь дрогое обладающее адресом и протяженностью.
И PChar(S) Pointer(S) полностью подходят, третий вариант передачи адреса, это операция взятия адреса @buf[n], для строки точно также. Естественно что во всех случаях "массив" должен существовать.
Твое представления об string абсолютно не верны, не знаю на чем они базируются. И Pointer и PChar вернут адрес первого байта буфера
← →
NA (2003-04-13 15:41) [31]Легко, уважаемый:
if RegQueryValueEx (Key, FoldName, nil, @D1, @Folder[1], @D2) = Error_Success
...необходимую инициализацию строки и реестра перед, надеюсь, допишете сами? При Ваших-то знаниях? :)))
← →
Giemgo (2003-04-13 16:17) [32]Anatoly Podgoretsky, в свою очередь хочу спросить - а где вы достали такое объявление ?
Если " И PChar(S) Pointer(S) полностью подходят"
то почему компилятор мне сообщает:
[Error] Unit1.pas(44): Constant object cannot be passed as var parameter
Насчет Pointer(s). Ведь вы не будете спорить, что string, если понимать под ним AnsiString - это не просто последовательность символов ? Вот поэтому я и усомнился в правильности Pointer(s)
NA, я вообще-то говорил про sendto, вам не кажется ?!. И еще раз, специально для тебя повторяю. СПЕЦИАЛЬНО. ПОСЛЕДНИЙ РАЗ.
Параметр должен передаваться по ССЫЛКЕ.
← →
NA (2003-04-13 20:59) [33]По-моему, тебе уже не один раз ответили.
← →
Giemgo (2003-04-13 22:19) [34]PChar(s) не подходит - я уже писал.
Просто Pointer(s) делает все неправильно. Ладно, возможно у меня ошибка в коде, еще поразбираюсь.
Остался вопрос, Pointer(s) и @s[1] это документированные ссылки ? То есть, могу я расчитывать, что в следующих версиях дельфи они будут работать также, даже если поменяется формат string ?
← →
jack128 (2003-04-13 23:02) [35]function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr;
tolen: Integer): Integer; stdcall;
При таком объявлении функции нужно писать так
var s : string;
begin
...
sendto(MySocket,s[1],...);
...
end;
Второй параметр это не указатель на буффер куда положут данные, а сам буффер. Думаю вам нужно понять разницу между указателем и ссылкой.
> Pointer(s) и @s[1] это документированные ссылки ?
По поводу первого варианта не скажу, а второй то точно всегда будет работать.
← →
default (2003-04-13 23:18) [36]function Length_(const S: String): LongWord;
begin
Result := LongWord(Pointer(LongWord(@S[1]) - 4)^)
end;
от этого ты наверно совсем офигеешь...
фигню ты говоришь насчёт того если формат поменяется -
указатель-то идёт на первый байт данных строки (не на байты её длины не на
счётчик ссылок(это для типа string)...)как бы формат не меняли данные-то останутся...
вот приведённая выше Length_ легко может "захромать" при изменении формата String поскольку
читает 4 байта длины строки типа String поэтому если раз-ки Delphi в следующей версии захотят
"переместить" эти данные то эта ф-ия работать будет не верно либо вообще вылетит с AV хотя это
маловероятно...понятно?!
← →
default (2003-04-13 23:35) [37]procedure TForm1.Button1Click(Sender: TObject);
var
Str: PChar;
begin
Str := "12345";
Caption := Char(Pointer(LongWord(Str) + 2)^); // Form1.Caption = "3"
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Str: PChar;
begin
Str := "12345";
if Pointer(Str) = @Str[0] then Caption := "Эквивалентно";
end;
надеюсь уж это всё прояснит...
помогло?
← →
NA (2003-04-14 00:48) [38]> LongWord(Pointer(LongWord(@S[1]) - 4)^)
ЖЖЖ>8 - [= - =]
:-)))
← →
Giemgo (2003-04-14 11:38) [39]jack128 © (13.04.03 23:02)
Да, вероятно в этом все дело. Вы не могли бы мне объяснить разницу между указателем и ссылкой ?
Просто я вот тут покопался. Оказывается PChar не указывает на данные, он указывает на область памяти, где записан адрес этих данных. Вот блин.
И если функции SendTo передать PChar, то она отправляет именно этот адрес. Честно говоря, я в недоумении, ведь по идее PChar это указатель на Char... а он указывает на адрес, по которому этот PChar расположен :(((((
← →
Anatoly Podgoretsky (2003-04-14 12:01) [40]Так не оказывается, по определению он должен указывать на строку ASCIIZ, но может указывать на что угодно, это уже в твоих руках.
В Дельфи 1 PChar был именно указателем на Char, теперь на строку.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2003.04.24;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.009 c