Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-76968
tytus
2003-04-12 23:53
2003.04.24
new style


4-77222
Andrej
2003-02-26 12:47
2003.04.24
Буфер


3-76780
msoftware
2003-04-03 09:26
2003.04.24
Помогите чайнику с TDecisionGrid


1-76913
Nico1a_____
2003-04-14 21:57
2003.04.24
HDC


3-76778
yurikon03
2003-04-04 09:30
2003.04.24
Как хранить суммы?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский