Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Data Pointer и все все все... [D7, XP]


Страницы:   1 2

Салат ©   (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"


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо