![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Data Pointer и все все все... [D7, XP]
Салат © (2007-08-06 19:40:00)Мне стыдно но я совсем не умею работать с указателями (Pointers) :( Расскажите в двух словах чайнику как через pointer работать с переменными (желательно на примере, где pointer будет указывать на record если такое возможно. если уж совсем близко то на примере TServerSocket.Socket.Connections[0].Data).
MsGuns (2007-08-07 16:45:00) [1]Указатели совершенно необходимы при работе со СПИСКАМИ однотипных сложных объектов (рекордов).
{RASkov} (2007-08-07 13:34:00) [2]> [27] Anatoly Podgoretsky © (07.08.07 13:24)
Абсолютно согласен.... и поэтому не стесняюсь спрашивать, если что не понятно....
Сергей М. (2007-08-07 13:31:00) [3]
> Салат (07.08.07 07:09) [25]
>
> Кто думает что указатели в моем случае не нужны сильно заблуждаются
Да что ты говоришь !?)
А мужики-то и не знают, что у тебя stNonBlocking)
Anatoly Podgoretsky (2007-08-07 13:24:00) [4]> {RASkov} (07.08.2007 13:18:26) [26]
Менять не обязательно, а вот знания обязательно, иначе ущербность в знаниях.
{RASkov} (2007-08-07 13:18:00) [5]> [25] Салат (07.08.07 07:09)
> Кто думает что указатели в моем случае не нужны сильно заблуждаются
И нечего здесь думать - не нужны они, тыж пример привел... [4]
> В моем примере было все очень упрощено
Ну так приведи другой пример.... наверняка они и там не нужны будут :)
К сожалению мне вот это:
> ServerSocket.Socket.Connections[].Data (который Pointer)
> с некими данными которые идентифицировали бы этот сокет.
... не о чем :(
> [24] Германн © (07.08.07 02:18)
Этот пример был только для доказательства, что адреса локальных констант сохраняються, а адреса переменных нет :)
А про указатели я свое мнение из [6] не поменяю.... пока, хоть и еще более ближе к ним(указателям) стал в этой ветке ;)
Салат (2007-08-07 07:09:00) [6]Кто думает что указатели в моем случае не нужны сильно заблуждаются :) В моем примере было все очень упрощено, на деле же нужно было связать ServerSocket.Socket.Connections[].Data (который Pointer) с некими данными которые идентифицировали бы этот сокет.
Германн (2007-08-07 02:18:00) [7]
> {RASkov} © (07.08.07 01:16) [23]
>
> > [21] Инс © (07.08.07 00:59)
>
> Точно,
> И вот доказательства:
>
Из сего примера первый вывод, который нужно сделать - не стОит плодить лишние сущности! А переменнаяClr: array [0..2] of TColorименно таковой и является. Не было б её, не было б и ошибок :)
{RASkov} (2007-08-07 01:16:00) [8]> [21] Инс © (07.08.07 00:59)
Точно,
И вот доказательства:
Так не работает:
procedure TForm1.Button4Click(Sender: TObject);
var Clr: array [0..2] of TColor;
begin
Clr[0]:=clRed; Clr[1]:=clBlue; Clr[2]:=clYellow;
ListView1.Items[2].Data:=@Clr[(Sender as TButton).Tag]; //пишем адрес локальной переменной
ListView1.Invalidate;
end;
if Item.Data<>nil then ListView1.Canvas.Brush.Color := TColor(Item.Data^); //пытаемся взять данные по "паленому" адресу
А так все ок:
procedure TForm1.Button4Click(Sender: TObject);
var Clr: array [0..2] of TColor;
begin
Clr[0]:=clRed; Clr[1]:=clBlue; Clr[2]:=clYellow;
ListView1.Items[2].Data:=Pointer(Clr[(Sender as TButton).Tag]); //Вместо адреса на данные используем сам адрес в качестве значения цвета
ListView1.Invalidate;
end;
if Item.Data<>nil then ListView1.Canvas.Brush.Color := TColor(Item.Data); //Адрес Pointer используем в качестве цвета, И разыменование приведет к ошибке, так как данных по этому адресу нет....
> [22] Инс © (07.08.07 01:04)
> Адрес константы имеет значение, близкое к $00400000 - это
> адрес, по которому образ exe загружен в виртуальное АП
Я не настолько знаком с этим, но вот .... учусь потихоньку :) Надеюсь урок усвоил правильно. Спасибо.
Инс (2007-08-07 01:04:00) [9]Вы сами смогли бы это проверить. Адрес константы имеет значение, близкое к $00400000 - это адрес, по которому образ exe загружен в виртуальное АП. Из этого можно сделать вывод, что константа "вшита" в exe. Стек располагается совсем по другому адресу.
Инс (2007-08-07 00:59:00) [10]
> всегда в памяти присутствует?
Да, конечно. Понятие "локальная" для констант подразумевает только то, что вы не сможете к ней обратиться из-за пределов подпрограммы. Но константа на то и константа, ее значение нельзя изменить, и для этого компилятор располагает ее в в области памяти, защищенной от записи, но не в стеке.
{RASkov} (2007-08-07 00:57:00) [11]> [17] Юрий Зотов © (07.08.07 00:53)
> Ее адрес фиксирован и жив, пока жива сама программа.
Все встало на свои места.... Спасибо.
Все понятно теперь.... разобрался.
{RASkov} (2007-08-07 00:56:00) [12]Со вторым разобрался, а вот...
> В первом случае мы в тэге сохраняем именно адрес. Потом,
> когда нужно получить значение цвета - разадресовываем.
Мне все вроде понятно, будь глобальные объекты, но..... У локальных переменных, констант адреса остаються? Они(локальные пер/конст) вроде как при входе "инициализируються" при выходе освобождаются (память), .... как адрес на константу "живет" в другом методе....
Нет... я с указателями наверное крепко не подружусь :( Вроде все понятно, а с другой стороны...
> [16] Инс © (07.08.07 00:47)
Мне все понятно, но по отношению к глобальным вещам, а как это у локальных обстоит.... т.е. константа:
const Clr: array [0..2] of TColor = (clRed, clBlue, clYellow);
всегда в памяти присутствует?
Инс (2007-08-07 00:54:00) [13]
> [17] Юрий Зотов © (07.08.07 00:53)
Дуэтом :)
Юрий Зотов (2007-08-07 00:53:00) [14]> {RASkov} © (07.08.07 00:26) [13]
В первом примере указатель живой потому, что компилятор разместил локальную константу в статической памяти. Ее адрес фиксирован и жив, пока жива сама программа.
Разыменование в первом примере нужно потому, что в Item.Data мы запоминали АДРЕС константы, а получить хотим ЗНАЧЕНИЕ этой константы. Во втором же примере в Item.Data мы запоминали не АДРЕС константы, а ее ЗНАЧЕНИЕ - поэтому разыменование не нужно.
Во втором примере использовался тот факт, что длина типов TColor и Pointer одинаковая (4 байта на 32-битных платформах), поэтому, если некая область (Item.Data) хранит некое число, то это число может быть и адресом, и цветом (да и вообще чем угодно: что мы туда положили - то там и будет). А чтобы компилятор не ругался на несоответствие типов, в коде второго примера дважды использовано явное приведение типа: при запоминании цвета в Item.Data тип TColor приводится к типу Pointer, а при чтении - наоборот.
Инс (2007-08-07 00:47:00) [15]
> а потом разыменовываем и преобразуем к TColor некий адрес
> констаны
Уже не адрес приводим, а значение. Сначала разадресация (теперь у нас вместо адреса значение, только непонятно какого типа), а потом - приводим к типу TColor. Я бы лучше написал так, понятнее:
... := PColor(Item.Data)^;
Инс (2007-08-07 00:43:00) [16]В первом случае мы в тэге сохраняем именно адрес. Потом, когда нужно получить значение цвета - разадресовываем. Во втором случае, мы сохраняем в тэге не адрес, а само значение, а приведение к Pointer делаем чтобы компилятор не ругался (так как свойство Data должно быть типа Pointer). Вот мы и заставляем компилятор думать, что TColor это Pointer. Раз в тэге НЕ адрес, то и разадресовывать не надо.
{RASkov} (2007-08-07 00:38:00) [17]Второй пример разобрался...
Пишем вместо адреса - некое число (clRed, clBlue...)
И потом этот адрес(грубо - число) преобразуем к TColor и все нормально, поэтому нам "не страшно", что была локальная константа...
А вот в первом пишем адрес константы, а потом разыменовываем и преобразуем к TColor некий адрес констаны, и ... в общем непонятно...
Точно пора спать (
{RASkov} (2007-08-07 00:26:00) [18]Вот опять запутался.... вы уж простите, что в чужой ветке, но автору тоже пойдет на пользу, так как его тоже интересует работа с указателями, а конкретного вопроса в топике не было...
Из соседней ветки:
Как все же правильнее, так:
procedure TForm1.Button4Click(Sender: TObject);
const Clr: array [0..2] of TColor = (clRed, clBlue, clYellow);
begin
ListView1.Items[2].Data := @Clr[(Sender as TButton).Tag]; //@ - адрес локальной константы
ListView1.Invalidate;
end;
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if Item.Data<>nil then ListView1.Canvas.Brush.Color := TColor(Item.Data ^); //нужно разыминование, и почему этот адрес живой
end;
или так:
procedure TForm1.Button4Click(Sender: TObject);
const Clr: array [0..2] of TColor = (clRed, clBlue, clYellow);
begin
ListView1.Items[2].Data := Pointer(Clr[(Sender as TButton).Tag]); //приводим к Pointer'у
ListView1.Invalidate;
end;
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
if Item.Data<>nil then ListView1.Canvas.Brush.Color := TColor(Item. Data); //Вроде нетипизированный указатель, а ^ не нужна
end;
или это одно и тоже? А то даю советы, а тут сам запутался :(
Оба примера рабочие.
Я так понимаю:
В первом примере- мы берем адрес локальной константы и пишем его в Data, а потом как этот локал адрес остается при разыменовании Data в другом месте? Повезло?
Во втором - ну здесь вроде более менее понятно... единственное только с крышкой не совсем понял...
Пора спать :)
{RASkov} (2007-08-07 00:05:00) [19]> [10] Юрий Зотов © (06.08.07 23:36)
Спасибо.... есть польза.
Т.е. у типизированных указателей крышу ставить не обязательно, но желательно, а у не типизированных (Pointer) - обязательно.
TMyRecord = record
str1 : String[255];
str2 : String[255];
i : Integer;
end;
PMyRecord = ^TMyRecord;
var
P: Pointer;
P1: PMyRecord;
.....
TMyRecord(P^).i:=5; - обязательна ^
P1^.i:=5; - ^ не обязательна
P1.i:=5;
> Никакой путаницы нет - надо только ОДИН раз понять
Самое обидное, это то, что я эти указатели, то понимаю, то нифика не понимаю... т.е. то они мне легко и просто даются, то как баран на них смотрю.
Другими словами можно конечно сказать, что я их не понимаю :(
Когда этих "крышек" нет то все ок, но когда они появляются, то вот здесь и бывают провалы...
Кстати.... пример в [3] довольно легко прочитался и понялся :) А в другом месте((примере), образно) могу запутаться :(
Ладно.... еще раз спасибо и сорри за оффтоп
Anatoly Podgoretsky (2007-08-06 23:59:00) [20]> Юрий Зотов (06.08.2007 23:36:10) [10]
> Да, компилятор Deplhi сам разыменовывает указатели. Любая объектная переменная ведь
> тоже указатель, поэтому по правилам Паскаля надо было бы писать, строго говоря, так:
> Button1^.Caption := 'OK';
> Но мы крышку не пишем, компилятор сам разыменовывает Button1.
Есть и исключение "Do not apply the dereference operator (^) to a dynamic-array variabl"