![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Data Pointer и все все все... [D7, XP]
Салат © (2007-08-06 19:40:00)Мне стыдно но я совсем не умею работать с указателями (Pointers) :( Расскажите в двух словах чайнику как через pointer работать с переменными (желательно на примере, где pointer будет указывать на record если такое возможно. если уж совсем близко то на примере TServerSocket.Socket.Connections[0].Data).
Юрий Зотов (2007-08-06 23:36:00) [21]> {RASkov} © (06.08.07 23:07) [8]
Да, компилятор Deplhi сам разыменовывает указатели. Любая объектная переменная ведь тоже указатель, поэтому по правилам Паскаля надо было бы писать, строго говоря, так:
Button1^.Caption := 'OK';
Но мы крышку не пишем, компилятор сам разыменовывает Button1.
Чтобы не путаться в своем же коде, я пользуюсь таким правилом: объектные переменные пусть разыменовывает компилятор, а простые (необъектные) указатели разыменовываю сам, по-старинке, явным образом. Это позволяет сразу отличать указатели от других типов переменных и правильно с ними работать (особенно, при использовании данных вида "указатель на указатель", когда требуется многократное разыменование).
> Вообщем с указателями только путаница
Никакой путаницы нет - надо только ОДИН раз понять, что это такое, а потом все будет очень просто. Указатели - штука для серьезного программиста совершенно необходимая (я бы даже сказал сильнее - кто не понимает указателей, того назвать программистом вообще нельзя). Без указателей нвозможно работать с динамической памятью напрямую (а это требуется частенько - например, при использовании многих функций WinAPI). Без понимания указателей нельзя толком понять и многие термины Delphi (длинная строка, динамический массив, объект, класс, VMT... и многое другое). Соответственно, не понимая этого, нельзя с этим и свободно работать - и именно от непонимания указателей бывает и много багов в программах, и много вопросов на форумах.
MetalFan (2007-08-06 23:24:00) [22]в случае с указателями на записи крышки можно и не ставить, среда и так поймет... но лучше, имхо, для наглядности все таки ставить ^
{RASkov} (2007-08-06 23:07:00) [23]> [5] MetalFan © (06.08.07 22:57)
Собственно... тоже пример по работе с указателями, но не их необходимости :)
Мои посты может быть такие, из-за того, что я панически "боюсь" их(указатели) :) И без надобности их не трогою....
Кстати вопрос по ним, если можно задам здесь в тему.... вот из [3]
Last ^.S := 'Элемент номер ' + IntToStr(Last ^.I);
Вот эти выделенные "крыши" - они непосредственно необходимы в данном месте или только для лучшего понимания, что есть что ??
Так как
Last.S := 'Элемент номер ' + IntToStr(Last.I);
Результат тот же....
"Крыша" - разыменование указателя, это я знаю..... Делфи наверняка, если их(крыши) не ставить, сама их подставляет, так?
Вообщем с указателями только путаница :)
Юрий Зотов (2007-08-06 23:07:00) [24]> Салат (06.08.07 22:48) [4]
В Вашем варианте указатель вовсе не нужен:
ShowMessage(clients[1].data);
И без всяких указателей.
Вообще, указатель - это просто-напросто переменная, которая содержит в себе адрес , только и всего. Если значение указателя равно nil, то это значит, что он пустой (то есть, не содержит в себе никакого адреса). Ничего сложного.
{RASkov} (2007-08-06 22:57:00) [25]> [4] Салат (06.08.07 22:48)
В данном примере никакого смысла нет в указателях....
И вообще указатели лучше не использовать, если нет на то особой необходимости. См пример из [3]
type
PData = ^TData; // Тип указателя на элемент стека
TData = record // Тип элемента стека
I: integer; // Данные элемента
S: string; // Еще данные элемента
Prev: PData; // Указатель на предыдущий элемент <----------- Иначе никак, а то можно было б лучше так Prev: TData
end;
MetalFan (2007-08-06 22:57:00) [26]хм... я раньше тоже не понимал) но однажды понял... но вот на пальцах объяснить не могу..
единственное, что в голову приходит: Pointer - это в общем случае просто 4 байта в памяти, "указывающие" на какую-либо область памяти или на nil...
к примеру:
type
TRec = record
Int: Integer;
W: Word;
Str: string;
end;
procedure Proc;
var
lInt: Integer;
lStr: string;
lRec: TRec;
lPtr: Pointer;
begin
lInt := 10;
lPtr := @lInt;
Integer(lPtr^) := 20;//изменили значение lInt
lStr := 'string';
lPtr := @lStr;
string(lPtr^) := 'asd';// изменили значение lStr;
lRec.Int := 100;
lRec.W := 1;
lRec.Str := 'sadssd';
lPtr := @lRec;
TRec(lPtr^).Int := 1;
TRec(lPtr^).W := 2;
TRec(lPtr^).Str := 'nnn';
end;
Салат (2007-08-06 22:48:00) [27]Спасибо, разобрался кое как :) вкривь и вкось сделал на массивах, но зато надежно, просто и работает. Для таких же как я может пригодится мой опыт:
TRecord = record
data: String[255];
end;
var
p: Pointer;
clients: array[0..2] of TRecord;
begin
p := @clients[1]; // связываем указатель с каким-то элементом массива
ShowMessage(TRecord(p^).data); // доступ к этому элементу
end;
Юрий Зотов (2007-08-06 22:33:00) [28]Построение стека записей:
type
PData = ^TData; // Тип указателя на элемент стека
TData = record // Тип элемента стека
I: integer; // Данные элемента
S: string; // Еще данные элемента
Prev: PData; // Указатель на предыдущий элемент
end;
var
Last: PData = nil; // Указатель на верхний элемент стека (пока пустого).
proсedure Push; // Создать новый элемент и затолкнуть его в стек.
var
P: PData;
begin
New(P); // Создали в динамической памяти новый элемент по адресу P.
P^.Prev := Last; // Разместили новый элемент на вершине стека.
Last := P // Протолкнули стек.
end;
proсedure Pop; // Вытолкнуть из стека верхний элемент и уничтожить его.
var
P: PData;
begin
if Last = nil then // Если стек пустой, то ничего делать не надо.
Exit;
P := Last; // Запомнили адрес верхнего элемента.
Last := Last^.Prev; // Вытолкнули верхний элемент из стека.
Dispose(P); // Освободили память, которую он занимал.
end;
procedure Clear; // Очистить стек и освободить всю занимаемую им память.
begin
while Last <> nil do
Pop
end;
var
i: integer;
begin
// Создать стек из 10 элементов
for i := 0 to 9 do
begin
Push;
Last^.I := i;
Last^.S := 'Элемент номер ' + IntToStr(Last^.I);
end;
// Уничтожить стек
Clear
end;
JanMihail (2007-08-06 22:04:00) [29]Сам толком не поинмаю, что за Pointer
JanMihail (2007-08-06 21:58:00) [30]type
MyRecord = record
str1: String[255];
str2: String[255];
i : Integer;
end;
var
Form1: TForm1;
a: MyRecord;
p: Pointer;
procedure TForm1.FormCreate(Sender: TObject);
begin
p := @a;
end;